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,12 +7,14 @@ import { Session } from 'src/session/Session';
|
|||||||
import { Admin } from 'src/admin/Admin';
|
import { Admin } from 'src/admin/Admin';
|
||||||
import { StoreContextProvider } from 'context/StoreContext';
|
import { StoreContextProvider } from 'context/StoreContext';
|
||||||
import { AppContextProvider } from 'context/AppContext';
|
import { AppContextProvider } from 'context/AppContext';
|
||||||
|
import { AccountContextProvider } from 'context/AccountContext';
|
||||||
import { ProfileContextProvider } from 'context/ProfileContext';
|
import { ProfileContextProvider } from 'context/ProfileContext';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StoreContextProvider>
|
<StoreContextProvider>
|
||||||
|
<AccountContextProvider>
|
||||||
<ProfileContextProvider>
|
<ProfileContextProvider>
|
||||||
<AppContextProvider>
|
<AppContextProvider>
|
||||||
<NativeRouter>
|
<NativeRouter>
|
||||||
@ -27,6 +29,7 @@ export default function App() {
|
|||||||
</NativeRouter>
|
</NativeRouter>
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</ProfileContextProvider>
|
</ProfileContextProvider>
|
||||||
|
</AccountContextProvider>
|
||||||
</StoreContextProvider>
|
</StoreContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||||
|
|
||||||
export async function getAccountStatus(token) {
|
export async function getAccountStatus(server, token) {
|
||||||
let status = await fetchWithTimeout('/account/status?agent=' + token, { method: 'GET' });
|
let status = await fetchWithTimeout(`https://${server}/account/status?agent=${token}`, { method: 'GET' });
|
||||||
checkResponse(status);
|
checkResponse(status);
|
||||||
return await status.json()
|
return await status.json()
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||||
import base64 from 'react-native-base64'
|
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()
|
let headers = new Headers()
|
||||||
headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password));
|
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);
|
checkResponse(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||||
|
|
||||||
export async function setAccountSearchable(token, flag) {
|
export async function setAccountSearchable(server, token, flag) {
|
||||||
let res = await fetchWithTimeout('/account/searchable?agent=' + token, { method: 'PUT', body: JSON.stringify(flag) })
|
let res = await fetchWithTimeout(`https://${server}/account/searchable?agent=${token}`, { method: 'PUT', body: JSON.stringify(flag) })
|
||||||
checkResponse(res);
|
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 { addAccount } from 'api/addAccount';
|
||||||
import { getUsername } from 'api/getUsername';
|
import { getUsername } from 'api/getUsername';
|
||||||
import { StoreContext } from 'context/StoreContext';
|
import { StoreContext } from 'context/StoreContext';
|
||||||
|
import { AccountContext } from 'context/AccountContext';
|
||||||
import { ProfileContext } from 'context/ProfileContext';
|
import { ProfileContext } from 'context/ProfileContext';
|
||||||
|
|
||||||
export function useAppContext() {
|
export function useAppContext() {
|
||||||
@ -13,6 +14,7 @@ export function useAppContext() {
|
|||||||
disconnected: null,
|
disconnected: null,
|
||||||
});
|
});
|
||||||
const store = useContext(StoreContext);
|
const store = useContext(StoreContext);
|
||||||
|
const account = useContext(AccountContext);
|
||||||
const profile = useContext(ProfileContext);
|
const profile = useContext(ProfileContext);
|
||||||
|
|
||||||
const delay = useRef(2);
|
const delay = useRef(2);
|
||||||
@ -37,12 +39,14 @@ export function useAppContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const setSession = async (access) => {
|
const setSession = async (access) => {
|
||||||
profile.actions.setSession(access);
|
await account.actions.setSession(access);
|
||||||
|
await profile.actions.setSession(access);
|
||||||
updateState({ session: true });
|
updateState({ session: true });
|
||||||
setWebsocket(access.server, access.appToken);
|
setWebsocket(access.server, access.appToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearSession = async () => {
|
const clearSession = async () => {
|
||||||
|
account.actions.clearSession();
|
||||||
profile.actions.clearSession();
|
profile.actions.clearSession();
|
||||||
updateState({ session: false });
|
updateState({ session: false });
|
||||||
clearWebsocket();
|
clearWebsocket();
|
||||||
@ -80,7 +84,8 @@ export function useAppContext() {
|
|||||||
ws.current.onmessage = (ev) => {
|
ws.current.onmessage = (ev) => {
|
||||||
try {
|
try {
|
||||||
const rev = JSON.parse(ev.data);
|
const rev = JSON.parse(ev.data);
|
||||||
profile.actions.setRevision(rev.profileRevision);
|
profile.actions.setRevision(rev.profile);
|
||||||
|
account.actions.setRevision(rev.account);
|
||||||
updateState({ disconnected: false });
|
updateState({ disconnected: false });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
|
@ -25,6 +25,7 @@ export function useProfileContext() {
|
|||||||
if (!syncing.current && setRevision.current !== curRevision.current) {
|
if (!syncing.current && setRevision.current !== curRevision.current) {
|
||||||
syncing.current = true;
|
syncing.current = true;
|
||||||
|
|
||||||
|
try {
|
||||||
const revision = curRevision.current;
|
const revision = curRevision.current;
|
||||||
const { server, appToken, guid } = session.current;
|
const { server, appToken, guid } = session.current;
|
||||||
const profile = await getProfile(server, appToken);
|
const profile = await getProfile(server, appToken);
|
||||||
@ -32,6 +33,10 @@ export function useProfileContext() {
|
|||||||
await store.actions.setProfileRevision(guid, revision);
|
await store.actions.setProfileRevision(guid, revision);
|
||||||
updateState({ profile, imageUrl: getProfileImageUrl(server, appToken, revision) });
|
updateState({ profile, imageUrl: getProfileImageUrl(server, appToken, revision) });
|
||||||
setRevision.current = revision;
|
setRevision.current = revision;
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
syncing.current = false;
|
syncing.current = false;
|
||||||
sync();
|
sync();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState, useRef, useContext } from 'react';
|
import { useEffect, useState, useRef, useContext } from 'react';
|
||||||
import SQLite from "react-native-sqlite-storage";
|
import SQLite from "react-native-sqlite-storage";
|
||||||
|
|
||||||
const DATABAG_DB = 'databag_v001.db';
|
const DATABAG_DB = 'databag_v005.db';
|
||||||
|
|
||||||
export function useStoreContext() {
|
export function useStoreContext() {
|
||||||
const [state, setState] = useState({});
|
const [state, setState] = useState({});
|
||||||
@ -26,13 +26,15 @@ export function useStoreContext() {
|
|||||||
clearSession: async () => {
|
clearSession: async () => {
|
||||||
await db.current.executeSql("UPDATE app set value=? WHERE key='session';", [null]);
|
await db.current.executeSql("UPDATE app set value=? WHERE key='session';", [null]);
|
||||||
},
|
},
|
||||||
|
|
||||||
getProfile: async (guid) => {
|
getProfile: async (guid) => {
|
||||||
const dataId = `${guid}_profile`;
|
const dataId = `${guid}_profile`;
|
||||||
return await getAppValue(db.current, dataId, {});
|
return await getAppValue(db.current, dataId, {});
|
||||||
},
|
},
|
||||||
setProfile: async (guid, profile) => {
|
setProfile: async (guid, profile) => {
|
||||||
const dataId = `${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) => {
|
getProfileRevision: async (guid) => {
|
||||||
const dataId = `${guid}_profileRevision`;
|
const dataId = `${guid}_profileRevision`;
|
||||||
@ -40,7 +42,27 @@ export function useStoreContext() {
|
|||||||
},
|
},
|
||||||
setProfileRevision: async (guid, revision) => {
|
setProfileRevision: async (guid, revision) => {
|
||||||
const dataId = `${guid}_profileRevision`;
|
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 }
|
return { state, actions }
|
||||||
@ -67,6 +89,14 @@ function hasResult(res) {
|
|||||||
return true;
|
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) {
|
async function getAppValue(sql: SQLite.SQLiteDatabase, id: string, unset) {
|
||||||
const res = await sql.executeSql(`SELECT * FROM app WHERE key='${id}';`);
|
const res = await sql.executeSql(`SELECT * FROM app WHERE key='${id}';`);
|
||||||
if (hasResult(res)) {
|
if (hasResult(res)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user