diff --git a/app/mobile/App.js b/app/mobile/App.js
index c72eb11e..b81fad99 100644
--- a/app/mobile/App.js
+++ b/app/mobile/App.js
@@ -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 (
-
-
-
-
- } />
- } />
- } />
- } />
- } />
- } />
-
-
-
-
+
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
+
);
}
diff --git a/app/mobile/src/api/getAccountStatus.js b/app/mobile/src/api/getAccountStatus.js
index 3f1f0fa6..4c7a7f4b 100644
--- a/app/mobile/src/api/getAccountStatus.js
+++ b/app/mobile/src/api/getAccountStatus.js
@@ -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()
}
diff --git a/app/mobile/src/api/setAccountLogin.js b/app/mobile/src/api/setAccountLogin.js
index 021dbc38..9365469c 100644
--- a/app/mobile/src/api/setAccountLogin.js
+++ b/app/mobile/src/api/setAccountLogin.js
@@ -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);
}
diff --git a/app/mobile/src/api/setAccountSearchable.js b/app/mobile/src/api/setAccountSearchable.js
index 84f357e5..57990d1a 100644
--- a/app/mobile/src/api/setAccountSearchable.js
+++ b/app/mobile/src/api/setAccountSearchable.js
@@ -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);
}
diff --git a/app/mobile/src/context/AccountContext.js b/app/mobile/src/context/AccountContext.js
new file mode 100644
index 00000000..e4c34613
--- /dev/null
+++ b/app/mobile/src/context/AccountContext.js
@@ -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 (
+
+ {children}
+
+ );
+}
+
diff --git a/app/mobile/src/context/useAccountContext.hook.js b/app/mobile/src/context/useAccountContext.hook.js
new file mode 100644
index 00000000..5e2c7031
--- /dev/null
+++ b/app/mobile/src/context/useAccountContext.hook.js
@@ -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 }
+}
+
+
diff --git a/app/mobile/src/context/useAppContext.hook.js b/app/mobile/src/context/useAppContext.hook.js
index d6051b50..60b9c4d9 100644
--- a/app/mobile/src/context/useAppContext.hook.js
+++ b/app/mobile/src/context/useAppContext.hook.js
@@ -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) {
diff --git a/app/mobile/src/context/useProfileContext.hook.js b/app/mobile/src/context/useProfileContext.hook.js
index ddb75d03..b3f92c42 100644
--- a/app/mobile/src/context/useProfileContext.hook.js
+++ b/app/mobile/src/context/useProfileContext.hook.js
@@ -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();
diff --git a/app/mobile/src/context/useStoreContext.hook.js b/app/mobile/src/context/useStoreContext.hook.js
index 8009dec4..89b68342 100644
--- a/app/mobile/src/context/useStoreContext.hook.js
+++ b/app/mobile/src/context/useStoreContext.hook.js
@@ -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)) {