diff --git a/app/mobile/App.js b/app/mobile/App.js
index ecc82175..c72eb11e 100644
--- a/app/mobile/App.js
+++ b/app/mobile/App.js
@@ -7,23 +7,26 @@ import { Session } from 'src/session/Session';
import { Admin } from 'src/admin/Admin';
import { StoreContextProvider } from 'context/StoreContext';
import { AppContextProvider } from 'context/AppContext';
+import { ProfileContextProvider } from 'context/ProfileContext';
export default function App() {
return (
-
-
-
- } />
- } />
- } />
- } />
- } />
- } />
-
-
-
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
);
}
diff --git a/app/mobile/src/api/getProfile.js b/app/mobile/src/api/getProfile.js
index 5fd6c1e2..7789e053 100644
--- a/app/mobile/src/api/getProfile.js
+++ b/app/mobile/src/api/getProfile.js
@@ -1,7 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
-export async function getProfile(token) {
- let profile = await fetchWithTimeout(`/profile?agent=${token}`, { method: 'GET' });
+export async function getProfile(server, token) {
+ let profile = await fetchWithTimeout(`https://${server}/profile?agent=${token}`, { method: 'GET' });
checkResponse(profile)
return await profile.json()
}
diff --git a/app/mobile/src/api/getProfileImageUrl.js b/app/mobile/src/api/getProfileImageUrl.js
index 038a7544..46d96a05 100644
--- a/app/mobile/src/api/getProfileImageUrl.js
+++ b/app/mobile/src/api/getProfileImageUrl.js
@@ -1,4 +1,4 @@
-export function getProfileImageUrl(token, revision) {
- return '/profile/image?agent=' + token + "&revision=" + revision
+export function getProfileImageUrl(server, token, revision) {
+ return `https://${server}/profile/image?agent=${token}&revision=${revision}`;
}
diff --git a/app/mobile/src/api/setProfileData.js b/app/mobile/src/api/setProfileData.js
index 00a405fc..e973b035 100644
--- a/app/mobile/src/api/setProfileData.js
+++ b/app/mobile/src/api/setProfileData.js
@@ -1,8 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
-export async function setProfileData(token, name, location, description) {
+export async function setProfileData(server, token, name, location, description) {
let data = { name: name, location: location, description: description };
- let profile = await fetchWithTimeout(`/profile/data?agent=${token}`, { method: 'PUT', body: JSON.stringify(data) });
+ let profile = await fetchWithTimeout(`https://${server}/profile/data?agent=${token}`, { method: 'PUT', body: JSON.stringify(data) });
checkResponse(profile)
return await profile.json()
}
diff --git a/app/mobile/src/api/setProfileImage.js b/app/mobile/src/api/setProfileImage.js
index 9eb46a11..a40cafe9 100644
--- a/app/mobile/src/api/setProfileImage.js
+++ b/app/mobile/src/api/setProfileImage.js
@@ -1,7 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
-export async function setProfileImage(token, image) {
- let profile = await fetchWithTimeout(`/profile/image?agent=${token}`, { method: 'PUT', body: JSON.stringify(image) });
+export async function setProfileImage(server, token, image) {
+ let profile = await fetchWithTimeout(`https://${server}/profile/image?agent=${token}`, { method: 'PUT', body: JSON.stringify(image) });
checkResponse(profile)
return await profile.json()
}
diff --git a/app/mobile/src/context/ProfileContext.js b/app/mobile/src/context/ProfileContext.js
new file mode 100644
index 00000000..ef48f314
--- /dev/null
+++ b/app/mobile/src/context/ProfileContext.js
@@ -0,0 +1,14 @@
+import { createContext } from 'react';
+import { useProfileContext } from './useProfileContext.hook';
+
+export const ProfileContext = createContext({});
+
+export function ProfileContextProvider({ children }) {
+ const { state, actions } = useProfileContext();
+ return (
+
+ {children}
+
+ );
+}
+
diff --git a/app/mobile/src/context/useAppContext.hook.js b/app/mobile/src/context/useAppContext.hook.js
index 686f3f36..d6051b50 100644
--- a/app/mobile/src/context/useAppContext.hook.js
+++ b/app/mobile/src/context/useAppContext.hook.js
@@ -5,25 +5,47 @@ import { setAccountAccess } from 'api/setAccountAccess';
import { addAccount } from 'api/addAccount';
import { getUsername } from 'api/getUsername';
import { StoreContext } from 'context/StoreContext';
+import { ProfileContext } from 'context/ProfileContext';
export function useAppContext() {
const [state, setState] = useState({
session: null,
disconnected: null,
});
- const [appRevision, setAppRevision] = useState();
const store = useContext(StoreContext);
+ const profile = useContext(ProfileContext);
const delay = useRef(2);
const ws = useRef(null);
- const revision = useRef(null);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }))
}
- const resetData = () => {
- revision.current = null;
+ useEffect(() => {
+ init();
+ }, []);
+
+ const init = async () => {
+ const access = await store.actions.init();
+ if (access) {
+ await setSession(access);
+ }
+ else {
+ updateState({ session: false });
+ }
+ }
+
+ const setSession = async (access) => {
+ profile.actions.setSession(access);
+ updateState({ session: true });
+ setWebsocket(access.server, access.appToken);
+ }
+
+ const clearSession = async () => {
+ profile.actions.clearSession();
+ updateState({ session: false });
+ clearWebsocket();
}
const actions = {
@@ -32,19 +54,22 @@ export function useAppContext() {
create: async (server, username, password, token) => {
await addAccount(server, username, password, token);
const access = await setLogin(username, server, password)
- store.actions.setSession({ ...access, server });
+ await setSession({ ...access, server });
+ await store.actions.setSession({ ...access, server});
},
access: async (server, token) => {
const access = await setAccountAccess(server, token);
- store.actions.setSession({ ...access, server });
+ await setSession({ ...access, server });
+ await store.actions.setSession({ ...access, server});
},
login: async (username, password) => {
const acc = username.split('@');
const access = await setLogin(acc[0], acc[1], password)
- store.actions.setSession({ ...access, server: acc[1] });
+ await setSession({ ...access, server: acc[1] });
+ await store.actions.setSession({ ...access, server: acc[1]});
},
logout: async () => {
- resetData();
+ await clearSession();
await store.actions.clearSession();
},
}
@@ -55,7 +80,7 @@ export function useAppContext() {
ws.current.onmessage = (ev) => {
try {
const rev = JSON.parse(ev.data);
- setAppRevision(rev);
+ profile.actions.setRevision(rev.profileRevision);
updateState({ disconnected: false });
}
catch (err) {
@@ -95,20 +120,6 @@ export function useAppContext() {
}
}
- useEffect(() => {
- if (store.state.init) {
- if (store.state.session) {
- const { server, appToken } = store.state.session;
- setWebsocket(server, appToken);
- updateState({ session: true });
- }
- else {
- clearWebsocket();
- updateState({ session: false });
- }
- }
- }, [store.state.session, store.state.init]);
-
return { state, actions }
}
diff --git a/app/mobile/src/context/useProfileContext.hook.js b/app/mobile/src/context/useProfileContext.hook.js
new file mode 100644
index 00000000..ddb75d03
--- /dev/null
+++ b/app/mobile/src/context/useProfileContext.hook.js
@@ -0,0 +1,72 @@
+import { useState, useRef, useContext } from 'react';
+import { getProfile } from 'api/getProfile';
+import { setProfileData } from 'api/setProfileData';
+import { setProfileImage } from 'api/setProfileImage';
+import { getProfileImageUrl } from 'api/getProfileImageUrl';
+import { StoreContext } from 'context/StoreContext';
+
+export function useProfileContext() {
+ const [state, setState] = useState({
+ profile: {},
+ imageUrl: null,
+ });
+ 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;
+
+ 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;
+
+ syncing.current = false;
+ sync();
+ }
+ };
+
+ const actions = {
+ setSession: async (access) => {
+ const { guid, server, appToken } = access;
+ const profile = await store.actions.getProfile(guid);
+ const revision = await store.actions.getProfileRevision(guid);
+ updateState({ profile, imageUrl: getProfileImageUrl(server, appToken, revision) });
+ setRevision.current = revision;
+ curRevision.current = revision;
+ session.current = access;
+ },
+ clearSession: () => {
+ session.current = {};
+ updateState({ profile: null });
+ },
+ setRevision: (rev) => {
+ curRevision.current = rev;
+ sync();
+ },
+ setProfileData: async (name, location, description) => {
+ const { server, appToken } = session.current;
+ await setProfileData(server, appToken, name, location, description);
+ },
+ setProfileImage: async (image) => {
+ const { server, appToken } = session.current;
+ await setProfileImage(server, appToken, image);
+ },
+ }
+
+ return { state, actions }
+}
+
+
diff --git a/app/mobile/src/context/useStoreContext.hook.js b/app/mobile/src/context/useStoreContext.hook.js
index a9164ea2..8009dec4 100644
--- a/app/mobile/src/context/useStoreContext.hook.js
+++ b/app/mobile/src/context/useStoreContext.hook.js
@@ -4,97 +4,45 @@ import SQLite from "react-native-sqlite-storage";
const DATABAG_DB = 'databag_v001.db';
export function useStoreContext() {
- const [state, setState] = useState({
- init: false,
- session: null,
- sessionId: 0,
- profileRevision: null,
- cardRevision: null,
- channelRevision: null,
- accountRevision: null,
- });
-
+ const [state, setState] = useState({});
const db = useRef(null);
- const session = useRef(null);
- const sessionId = useRef(0);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }))
}
- useEffect(() => {
- initialize();
- }, []);
-
- useEffect(() => {
- if (state.init && state.session && sessionId.current === state.sessionId) {
- const revision = {
- accountRevision: state.accountRevision,
- profileRevision: state.profileRevision,
- cardRevision: state.cardRevision,
- channelRevision: state.channelRevision,
- }
- const revisionId = `${session.current.guid}_revision`;
- db.current.executeSql(`UPDATE app SET value=? WHERE key='${revisionId}';`, [encodeObject(revision)]);
- }
- }, [state]);
-
- const initialize = async () => {
- SQLite.DEBUG(false);
- SQLite.enablePromise(true);
- db.current = await SQLite.openDatabase({ name: DATABAG_DB, location: "default" });
- await db.current.executeSql("CREATE TABLE IF NOT EXISTS app (key text, value text, unique(key));");
- await db.current.executeSql("INSERT OR IGNORE INTO app (key, value) values ('session', null);");
-
- session.current = await getAppValue(db.current, 'session');
- if (!session.current) {
- updateState({ init: true });
- }
- else {
- const revisionId = `${session.current.guid}_revision`;
- const revision = await getAppValue(db.current, revisionId, {});
- updateState({ init: true, session: session.current, ...revision });
- }
- };
-
const actions = {
+ init: async () => {
+ SQLite.DEBUG(false);
+ SQLite.enablePromise(true);
+ db.current = await SQLite.openDatabase({ name: DATABAG_DB, location: "default" });
+ await db.current.executeSql("CREATE TABLE IF NOT EXISTS app (key text, value text, unique(key));");
+ await db.current.executeSql("INSERT OR IGNORE INTO app (key, value) values ('session', null);");
+ return await getAppValue(db.current, 'session');
+ },
setSession: async (access) => {
await db.current.executeSql("UPDATE app SET value=? WHERE key='session';", [encodeObject(access)]);
-
- const revisionId = `${access.guid}_revision`;
- const revision = await getAppValue(db.current, revisionId, {});
-
- session.current = access;
- sessionId.current++;
- updateState({ session: access, sessionId: sessionId.current, ...revision });
},
clearSession: async () => {
await db.current.executeSql("UPDATE app set value=? WHERE key='session';", [null]);
- session.current = null;
- updateState({ session: null });
},
- setProfileRevision: (id, profileRevision) => {
- if (sessionId.current === id) {
- updateState({ profileRevision });
- }
+ getProfile: async (guid) => {
+ const dataId = `${guid}_profile`;
+ return await getAppValue(db.current, dataId, {});
},
- setAccountRevision: (id, accountRevision) => {
- if (sessionId.current === id) {
- updateState({ accountRevision });
- }
+ setProfile: async (guid, profile) => {
+ const dataId = `${guid}_profile`;
+ await db.current.executeSql("UPDATE app SET value=? WHERE key='?';", [encodeObject(profile)], dataId);
},
- setCardRevision: (id, cardRevision) => {
- if (sessionId.current === id) {
- updateState({ cardRevision });
- }
+ getProfileRevision: async (guid) => {
+ const dataId = `${guid}_profileRevision`;
+ return await getAppValue(db.current, dataId, 0);
},
- setChannelRevision: (channelRevision) => {
- if (sessionId.current === id) {
- updateState({ channelRevision });
- }
+ setProfileRevision: async (guid, revision) => {
+ const dataId = `${guid}_profileRevision`;
+ await db.current.executeSql("UPDATE app SET value=? WHERE key='?';", [encodeObject(revision)], dataId);
},
}
-
return { state, actions }
}