mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
syncing account and profile
This commit is contained in:
parent
4ca0f53da1
commit
33966512f1
@ -7,26 +7,29 @@ import { Session } from 'src/session/Session';
|
||||
import { Admin } from 'src/admin/Admin';
|
||||
import { StoreContextProvider } from 'context/StoreContext';
|
||||
import { AppContextProvider } from 'context/AppContext';
|
||||
import { AccountContextProvider } from 'context/AccountContext';
|
||||
import { ProfileContextProvider } from 'context/ProfileContext';
|
||||
|
||||
export default function App() {
|
||||
|
||||
return (
|
||||
<StoreContextProvider>
|
||||
<ProfileContextProvider>
|
||||
<AppContextProvider>
|
||||
<NativeRouter>
|
||||
<Routes>
|
||||
<Route path="/" element={ <Root /> } />
|
||||
<Route path="/admin" element={ <Admin /> } />
|
||||
<Route path="/login" element={ <Access mode="login" /> } />
|
||||
<Route path="/reset" element={ <Access mode="reset" /> } />
|
||||
<Route path="/create" element={ <Access mode="create" /> } />
|
||||
<Route path="/session" element={ <Session/> } />
|
||||
</Routes>
|
||||
</NativeRouter>
|
||||
</AppContextProvider>
|
||||
</ProfileContextProvider>
|
||||
<AccountContextProvider>
|
||||
<ProfileContextProvider>
|
||||
<AppContextProvider>
|
||||
<NativeRouter>
|
||||
<Routes>
|
||||
<Route path="/" element={ <Root /> } />
|
||||
<Route path="/admin" element={ <Admin /> } />
|
||||
<Route path="/login" element={ <Access mode="login" /> } />
|
||||
<Route path="/reset" element={ <Access mode="reset" /> } />
|
||||
<Route path="/create" element={ <Access mode="create" /> } />
|
||||
<Route path="/session" element={ <Session/> } />
|
||||
</Routes>
|
||||
</NativeRouter>
|
||||
</AppContextProvider>
|
||||
</ProfileContextProvider>
|
||||
</AccountContextProvider>
|
||||
</StoreContextProvider>
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function getAccountStatus(token) {
|
||||
let status = await fetchWithTimeout('/account/status?agent=' + token, { method: 'GET' });
|
||||
export async function getAccountStatus(server, token) {
|
||||
let status = await fetchWithTimeout(`https://${server}/account/status?agent=${token}`, { method: 'GET' });
|
||||
checkResponse(status);
|
||||
return await status.json()
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
import base64 from 'react-native-base64'
|
||||
|
||||
export async function setAccountLogin(token, username, password) {
|
||||
export async function setAccountLogin(server, token, username, password) {
|
||||
let headers = new Headers()
|
||||
headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password));
|
||||
let res = await fetchWithTimeout(`/account/login?agent=${token}`, { method: 'PUT', headers })
|
||||
let res = await fetchWithTimeout(`https://${server}/account/login?agent=${token}`, { method: 'PUT', headers })
|
||||
checkResponse(res);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function setAccountSearchable(token, flag) {
|
||||
let res = await fetchWithTimeout('/account/searchable?agent=' + token, { method: 'PUT', body: JSON.stringify(flag) })
|
||||
export async function setAccountSearchable(server, token, flag) {
|
||||
let res = await fetchWithTimeout(`https://${server}/account/searchable?agent=${token}`, { method: 'PUT', body: JSON.stringify(flag) })
|
||||
checkResponse(res);
|
||||
}
|
||||
|
||||
|
14
app/mobile/src/context/AccountContext.js
Normal file
14
app/mobile/src/context/AccountContext.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { createContext } from 'react';
|
||||
import { useAccountContext } from './useAccountContext.hook';
|
||||
|
||||
export const AccountContext = createContext({});
|
||||
|
||||
export function AccountContextProvider({ children }) {
|
||||
const { state, actions } = useAccountContext();
|
||||
return (
|
||||
<AccountContext.Provider value={{ state, actions }}>
|
||||
{children}
|
||||
</AccountContext.Provider>
|
||||
);
|
||||
}
|
||||
|
75
app/mobile/src/context/useAccountContext.hook.js
Normal file
75
app/mobile/src/context/useAccountContext.hook.js
Normal file
@ -0,0 +1,75 @@
|
||||
import { useState, useRef, useContext } from 'react';
|
||||
import { StoreContext } from 'context/StoreContext';
|
||||
import { setAccountSearchable } from 'api/setAccountSearchable';
|
||||
import { getAccountStatus } from 'api/getAccountStatus';
|
||||
import { setAccountLogin } from 'api/setAccountLogin';
|
||||
|
||||
export function useAccountContext() {
|
||||
const [state, setState] = useState({
|
||||
status: {},
|
||||
});
|
||||
const store = useContext(StoreContext);
|
||||
|
||||
const session = useRef(null);
|
||||
const curRevision = useRef(null);
|
||||
const setRevision = useRef(null);
|
||||
const syncing = useRef(false);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }))
|
||||
}
|
||||
|
||||
const sync = async () => {
|
||||
if (!syncing.current && setRevision.current !== curRevision.current) {
|
||||
syncing.current = true;
|
||||
|
||||
try {
|
||||
const revision = curRevision.current;
|
||||
const { server, appToken, guid } = session.current;
|
||||
const status = await getAccountStatus(server, appToken);
|
||||
await store.actions.setAccountStatus(guid, status);
|
||||
await store.actions.setAccountRevision(guid, revision);
|
||||
updateState({ status });
|
||||
setRevision.current = revision;
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
syncing.current = false;
|
||||
sync();
|
||||
}
|
||||
};
|
||||
|
||||
const actions = {
|
||||
setSession: async (access) => {
|
||||
const { guid, server, appToken } = access;
|
||||
const status = await store.actions.getAccountStatus(guid);
|
||||
const revision = await store.actions.getAccountRevision(guid);
|
||||
updateState({ status });
|
||||
setRevision.current = revision;
|
||||
curRevision.current = revision;
|
||||
session.current = access;
|
||||
},
|
||||
clearSession: () => {
|
||||
session.current = {};
|
||||
updateState({ account: null });
|
||||
},
|
||||
setRevision: (rev) => {
|
||||
curRevision.current = rev;
|
||||
sync();
|
||||
},
|
||||
setSearchable: async (flag) => {
|
||||
const { server, appToken } = access;
|
||||
await setAccountSearchable(server, appToken, flag);
|
||||
},
|
||||
setLogin: async (username, password) => {
|
||||
const { server, appToken } = access;
|
||||
await setAccountLogin(server, appToken, username, password);
|
||||
},
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import { setAccountAccess } from 'api/setAccountAccess';
|
||||
import { addAccount } from 'api/addAccount';
|
||||
import { getUsername } from 'api/getUsername';
|
||||
import { StoreContext } from 'context/StoreContext';
|
||||
import { AccountContext } from 'context/AccountContext';
|
||||
import { ProfileContext } from 'context/ProfileContext';
|
||||
|
||||
export function useAppContext() {
|
||||
@ -13,6 +14,7 @@ export function useAppContext() {
|
||||
disconnected: null,
|
||||
});
|
||||
const store = useContext(StoreContext);
|
||||
const account = useContext(AccountContext);
|
||||
const profile = useContext(ProfileContext);
|
||||
|
||||
const delay = useRef(2);
|
||||
@ -37,12 +39,14 @@ export function useAppContext() {
|
||||
}
|
||||
|
||||
const setSession = async (access) => {
|
||||
profile.actions.setSession(access);
|
||||
await account.actions.setSession(access);
|
||||
await profile.actions.setSession(access);
|
||||
updateState({ session: true });
|
||||
setWebsocket(access.server, access.appToken);
|
||||
}
|
||||
|
||||
const clearSession = async () => {
|
||||
account.actions.clearSession();
|
||||
profile.actions.clearSession();
|
||||
updateState({ session: false });
|
||||
clearWebsocket();
|
||||
@ -80,7 +84,8 @@ export function useAppContext() {
|
||||
ws.current.onmessage = (ev) => {
|
||||
try {
|
||||
const rev = JSON.parse(ev.data);
|
||||
profile.actions.setRevision(rev.profileRevision);
|
||||
profile.actions.setRevision(rev.profile);
|
||||
account.actions.setRevision(rev.account);
|
||||
updateState({ disconnected: false });
|
||||
}
|
||||
catch (err) {
|
||||
|
@ -25,13 +25,18 @@ export function useProfileContext() {
|
||||
if (!syncing.current && setRevision.current !== curRevision.current) {
|
||||
syncing.current = true;
|
||||
|
||||
const revision = curRevision.current;
|
||||
const { server, appToken, guid } = session.current;
|
||||
const profile = await getProfile(server, appToken);
|
||||
await store.actions.setProfile(guid, profile);
|
||||
await store.actions.setProfileRevision(guid, revision);
|
||||
updateState({ profile, imageUrl: getProfileImageUrl(server, appToken, revision) });
|
||||
setRevision.current = revision;
|
||||
try {
|
||||
const revision = curRevision.current;
|
||||
const { server, appToken, guid } = session.current;
|
||||
const profile = await getProfile(server, appToken);
|
||||
await store.actions.setProfile(guid, profile);
|
||||
await store.actions.setProfileRevision(guid, revision);
|
||||
updateState({ profile, imageUrl: getProfileImageUrl(server, appToken, revision) });
|
||||
setRevision.current = revision;
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
syncing.current = false;
|
||||
sync();
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, useRef, useContext } from 'react';
|
||||
import SQLite from "react-native-sqlite-storage";
|
||||
|
||||
const DATABAG_DB = 'databag_v001.db';
|
||||
const DATABAG_DB = 'databag_v005.db';
|
||||
|
||||
export function useStoreContext() {
|
||||
const [state, setState] = useState({});
|
||||
@ -26,13 +26,15 @@ export function useStoreContext() {
|
||||
clearSession: async () => {
|
||||
await db.current.executeSql("UPDATE app set value=? WHERE key='session';", [null]);
|
||||
},
|
||||
|
||||
getProfile: async (guid) => {
|
||||
const dataId = `${guid}_profile`;
|
||||
return await getAppValue(db.current, dataId, {});
|
||||
},
|
||||
setProfile: async (guid, profile) => {
|
||||
const dataId = `${guid}_profile`;
|
||||
await db.current.executeSql("UPDATE app SET value=? WHERE key='?';", [encodeObject(profile)], dataId);
|
||||
await db.current.executeSql("INSERT OR IGNORE INTO app (key, value) values (?, null);", [dataId]);
|
||||
await db.current.executeSql("UPDATE app SET value=? WHERE key=?;", [encodeObject(profile), dataId]);
|
||||
},
|
||||
getProfileRevision: async (guid) => {
|
||||
const dataId = `${guid}_profileRevision`;
|
||||
@ -40,8 +42,28 @@ export function useStoreContext() {
|
||||
},
|
||||
setProfileRevision: async (guid, revision) => {
|
||||
const dataId = `${guid}_profileRevision`;
|
||||
await db.current.executeSql("UPDATE app SET value=? WHERE key='?';", [encodeObject(revision)], dataId);
|
||||
await db.current.executeSql("INSERT OR IGNORE INTO app (key, value) values (?, 0);", [dataId]);
|
||||
await db.current.executeSql("UPDATE app SET value=? WHERE key=?;", [encodeObject(revision), dataId]);
|
||||
},
|
||||
|
||||
getAccountStatus: async (guid) => {
|
||||
const dataId = `${guid}_status`;
|
||||
return await getAppValue(db.current, dataId, {});
|
||||
},
|
||||
setAccountStatus: async (guid, status) => {
|
||||
const dataId = `${guid}_status`;
|
||||
await db.current.executeSql("INSERT OR IGNORE INTO app (key, value) values (?, null);", [dataId]);
|
||||
await db.current.executeSql("UPDATE app SET value=? WHERE key=?;", [encodeObject(status), dataId]);
|
||||
},
|
||||
getAccountRevision: async (guid) => {
|
||||
const dataId = `${guid}_accountRevision`;
|
||||
return await getAppValue(db.current, dataId, 0);
|
||||
},
|
||||
setAccountRevision: async (guid, revision) => {
|
||||
const dataId = `${guid}_accountRevision`;
|
||||
await db.current.executeSql("INSERT OR IGNORE INTO app (key, value) values (?, 0);", [dataId]);
|
||||
await db.current.executeSql("UPDATE app SET value=? WHERE key=?;", [encodeObject(revision), dataId]);
|
||||
},
|
||||
}
|
||||
return { state, actions }
|
||||
}
|
||||
@ -67,6 +89,14 @@ function hasResult(res) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function executeSql(sql: SQLite.SQLiteDatabase, query, params, uset) {
|
||||
return new Promise((resolve, reject) => {
|
||||
sql.executeSql(query, params, (tx, results) => {
|
||||
resolve(results);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function getAppValue(sql: SQLite.SQLiteDatabase, id: string, unset) {
|
||||
const res = await sql.executeSql(`SELECT * FROM app WHERE key='${id}';`);
|
||||
if (hasResult(res)) {
|
||||
|
Loading…
Reference in New Issue
Block a user