Implemented persistent storage when using cordova
|
@ -1,28 +1,16 @@
|
|||
import { LocalStorage, SessionStorage } from 'quasar';
|
||||
import { SessionStorage } from 'quasar';
|
||||
import { FG_Plugin } from '@flaschengeist/types';
|
||||
import { useSessionStore, useUserStore } from '.';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { api } from '../internal';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
function loadCurrentSession() {
|
||||
const session = LocalStorage.getItem<FG.Session>('session');
|
||||
if (session) session.expires = new Date(session.expires);
|
||||
return session || undefined;
|
||||
}
|
||||
|
||||
function loadUser() {
|
||||
const user = SessionStorage.getItem<FG.User>('user');
|
||||
if (user && user.birthday) user.birthday = new Date(user.birthday);
|
||||
return user || undefined;
|
||||
}
|
||||
|
||||
export const useMainStore = defineStore({
|
||||
id: 'main',
|
||||
|
||||
state: () => ({
|
||||
session: loadCurrentSession(),
|
||||
user: loadUser(),
|
||||
session: undefined as FG.Session | undefined,
|
||||
user: undefined as FG.User | undefined,
|
||||
notifications: [] as Array<FG_Plugin.Notification>,
|
||||
shortcuts: [] as Array<FG_Plugin.MenuLink>,
|
||||
}),
|
||||
|
@ -65,7 +53,6 @@ export const useMainStore = defineStore({
|
|||
const { data } = await api.post<FG.Session>('/auth', { userid, password });
|
||||
this.session = data;
|
||||
this.session.expires = new Date(this.session.expires);
|
||||
LocalStorage.set('session', this.session);
|
||||
return true;
|
||||
} catch ({ response }) {
|
||||
return (<AxiosResponse | undefined>response)?.status || false;
|
||||
|
@ -144,11 +131,11 @@ export const useMainStore = defineStore({
|
|||
await api.put(`users/${this.currentUser.userid}/shortcuts`, this.shortcuts);
|
||||
},
|
||||
handleLoggedOut() {
|
||||
LocalStorage.clear();
|
||||
|
||||
this.$patch({
|
||||
session: undefined,
|
||||
user: undefined,
|
||||
notifications: [],
|
||||
shortcuts: [],
|
||||
});
|
||||
SessionStorage.clear();
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<widget id="de.wu5.flaschengeist" version="2.0.0-alpha.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
<name>Flaschengeist</name>
|
||||
<name>flaschengeist-frontend</name>
|
||||
<description>Modular student club administration system</description>
|
||||
<author email="dev@cordova.apache.org" href="http://cordova.io">
|
||||
Apache Cordova Team
|
||||
|
@ -15,62 +15,10 @@
|
|||
<allow-intent href="geo:*" />
|
||||
<platform name="android">
|
||||
<allow-intent href="market:*" />
|
||||
<icon density="ldpi" src="res/android/ldpi.png" />
|
||||
<icon density="mdpi" src="res/android/mdpi.png" />
|
||||
<icon density="hdpi" src="res/android/hdpi.png" />
|
||||
<icon density="xhdpi" src="res/android/xhdpi.png" />
|
||||
<icon density="xxhdpi" src="res/android/xxhdpi.png" />
|
||||
<icon density="xxxhdpi" src="res/android/xxxhdpi.png" />
|
||||
<splash density="land-ldpi" src="res/screen/android/splash-land-ldpi.png" />
|
||||
<splash density="port-ldpi" src="res/screen/android/splash-port-ldpi.png" />
|
||||
<splash density="land-mdpi" src="res/screen/android/splash-land-mdpi.png" />
|
||||
<splash density="port-mdpi" src="res/screen/android/splash-port-mdpi.png" />
|
||||
<splash density="land-hdpi" src="res/screen/android/splash-land-hdpi.png" />
|
||||
<splash density="port-hdpi" src="res/screen/android/splash-port-hdpi.png" />
|
||||
<splash density="land-xhdpi" src="res/screen/android/splash-land-xhdpi.png" />
|
||||
<splash density="port-xhdpi" src="res/screen/android/splash-port-xhdpi.png" />
|
||||
<splash density="land-xxhdpi" src="res/screen/android/splash-land-xxhdpi.png" />
|
||||
<splash density="port-xxhdpi" src="res/screen/android/splash-port-xxhdpi.png" />
|
||||
<splash density="land-xxxhdpi" src="res/screen/android/splash-land-xxxhdpi.png" />
|
||||
<splash density="port-xxxhdpi" src="res/screen/android/splash-port-xxxhdpi.png" />
|
||||
</platform>
|
||||
<platform name="ios">
|
||||
<allow-intent href="itms:*" />
|
||||
<allow-intent href="itms-apps:*" />
|
||||
<icon height="57" src="res/ios/icon.png" width="57" />
|
||||
<icon height="114" src="res/ios/icon@2x.png" width="114" />
|
||||
<icon height="40" src="res/ios/icon-20@2x.png" width="40" />
|
||||
<icon height="60" src="res/ios/icon-20@3x.png" width="60" />
|
||||
<icon height="29" src="res/ios/icon-29.png" width="29" />
|
||||
<icon height="58" src="res/ios/icon-29@2x.png" width="58" />
|
||||
<icon height="87" src="res/ios/icon-29@3x.png" width="87" />
|
||||
<icon height="80" src="res/ios/icon-40@2x.png" width="80" />
|
||||
<icon height="120" src="res/ios/icon-60@2x.png" width="120" />
|
||||
<icon height="180" src="res/ios/icon-60@3x.png" width="180" />
|
||||
<icon height="20" src="res/ios/icon-20.png" width="20" />
|
||||
<icon height="40" src="res/ios/icon-40.png" width="40" />
|
||||
<icon height="50" src="res/ios/icon-50.png" width="50" />
|
||||
<icon height="100" src="res/ios/icon-50@2x.png" width="100" />
|
||||
<icon height="72" src="res/ios/icon-72.png" width="72" />
|
||||
<icon height="144" src="res/ios/icon-72@2x.png" width="144" />
|
||||
<icon height="76" src="res/ios/icon-76.png" width="76" />
|
||||
<icon height="152" src="res/ios/icon-76@2x.png" width="152" />
|
||||
<icon height="167" src="res/ios/icon-83.5@2x.png" width="167" />
|
||||
<icon height="1024" src="res/ios/icon-1024.png" width="1024" />
|
||||
<icon height="48" src="res/ios/icon-24@2x.png" width="48" />
|
||||
<icon height="55" src="res/ios/icon-27.5@2x.png" width="55" />
|
||||
<icon height="88" src="res/ios/icon-44@2x.png" width="88" />
|
||||
<icon height="172" src="res/ios/icon-86@2x.png" width="172" />
|
||||
<icon height="196" src="res/ios/icon-98@2x.png" width="196" />
|
||||
<splash src="res/screen/ios/Default@2x~iphone~anyany.png" />
|
||||
<splash src="res/screen/ios/Default@2x~iphone~comany.png" />
|
||||
<splash src="res/screen/ios/Default@2x~iphone~comcom.png" />
|
||||
<splash src="res/screen/ios/Default@3x~iphone~anyany.png" />
|
||||
<splash src="res/screen/ios/Default@3x~iphone~anycom.png" />
|
||||
<splash src="res/screen/ios/Default@3x~iphone~comany.png" />
|
||||
<splash src="res/screen/ios/Default@2x~ipad~anyany.png" />
|
||||
<splash src="res/screen/ios/Default@2x~ipad~comany.png" />
|
||||
</platform>
|
||||
<allow-navigation href="about:*" />
|
||||
<preference name="SplashMaintainAspectRatio" value="true" />
|
||||
</widget>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "de.wu5.flaschengeist",
|
||||
"displayName": "Flaschengeist",
|
||||
"name": "dev.flaschengeist",
|
||||
"displayName": "flaschengeist-frontend",
|
||||
"version": "1.0.0",
|
||||
"description": "A sample Apache Cordova application that responds to the deviceready event.",
|
||||
"main": "index.js",
|
||||
|
@ -13,18 +13,17 @@
|
|||
"author": "Apache Cordova Team",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"cordova-android": "^9.0.0",
|
||||
"cordova-android": "^9.1.0",
|
||||
"cordova-ios": "^6.1.1",
|
||||
"cordova-plugin-splashscreen": "^6.0.0",
|
||||
"cordova-plugin-nativestorage": "^2.3.2",
|
||||
"cordova-plugin-whitelist": "^1.3.4"
|
||||
},
|
||||
"cordova": {
|
||||
"plugins": {
|
||||
"cordova-plugin-whitelist": {},
|
||||
"cordova-plugin-splashscreen": {}
|
||||
"cordova-plugin-nativestorage": {}
|
||||
},
|
||||
"platforms": [
|
||||
"ios",
|
||||
"android"
|
||||
]
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 913 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 370 B |
Before Width: | Height: | Size: 702 B |
Before Width: | Height: | Size: 1022 B |
Before Width: | Height: | Size: 801 B |
Before Width: | Height: | Size: 969 B |
Before Width: | Height: | Size: 529 B |
Before Width: | Height: | Size: 1015 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 702 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 885 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 996 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 8.5 KiB |
|
@ -1,9 +1,50 @@
|
|||
import { useMainStore, pinia } from '@flaschengeist/api';
|
||||
import { LocalStorage } from 'quasar';
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import { useMainStore, pinia } from '@flaschengeist/api';
|
||||
|
||||
function isCordova() {
|
||||
return window.hasOwnProperty('cordova');
|
||||
}
|
||||
|
||||
function error() {
|
||||
console.debug('NativeStorage Error');
|
||||
}
|
||||
|
||||
export default boot(({ app }) => {
|
||||
app.use(pinia);
|
||||
|
||||
document.addEventListener('deviceready', () => {
|
||||
const store = useMainStore();
|
||||
|
||||
// Load main state from storage
|
||||
if (isCordova()) {
|
||||
// is cordova, so use Native Storage
|
||||
window.NativeStorage.keys((keys) => {
|
||||
// Check if key is set
|
||||
if (keys.includes('main_store'))
|
||||
window.NativeStorage.getItem<typeof store.$state>(
|
||||
'main_store',
|
||||
(v) => {
|
||||
// Check is object, then patch it
|
||||
if (typeof v === 'object') store.$patch(v);
|
||||
},
|
||||
error
|
||||
);
|
||||
}, error);
|
||||
} else {
|
||||
// is not cordova, so use LocalStorage
|
||||
store.$patch(LocalStorage.getItem<typeof store.$state>('main_store') || {});
|
||||
}
|
||||
|
||||
// Subscript to save changes of state to storage
|
||||
store.$subscribe(
|
||||
(mutation, state) => {
|
||||
if (isCordova()) window.NativeStorage.setItem('main_store', state, () => undefined, error);
|
||||
else LocalStorage.set('main_store', state);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
void store.init();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* @name Native Storage
|
||||
* @premier nativestorage
|
||||
* @description Native storage of variables in Android and iOS
|
||||
*
|
||||
* @usage
|
||||
* ```typescript
|
||||
* import { NativeStorage } from '@ionic-native/native-storage/ngx';
|
||||
*
|
||||
* constructor(private nativeStorage: NativeStorage) { }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* this.nativeStorage.setItem('myitem', {property: 'value', anotherProperty: 'anotherValue'})
|
||||
* .then(
|
||||
* () => console.log('Stored item!'),
|
||||
* error => console.error('Error storing item', error)
|
||||
* );
|
||||
*
|
||||
* this.nativeStorage.getItem('myitem')
|
||||
* .then(
|
||||
* data => console.log(data),
|
||||
* error => console.error(error)
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export {};
|
||||
|
||||
declare class NativeStorageOriginal {
|
||||
/**
|
||||
* Initialises shared storage with the suite name when using app groups in iOS
|
||||
* @param reference {string}
|
||||
*/
|
||||
initWithSuiteName(reference: string, success: () => void, error: () => void): void;
|
||||
/**
|
||||
* Stores a value
|
||||
* @param reference {string}
|
||||
* @param value
|
||||
*/
|
||||
setItem(reference: string, value: unknown, success: () => void, error: () => void): void;
|
||||
/**
|
||||
* Gets a stored item
|
||||
* @param reference {string}
|
||||
*/
|
||||
getItem<T = unknown>(reference: string, success: (obj: T) => void, error: () => void): void;
|
||||
/**
|
||||
* Retrieving all keys
|
||||
*/
|
||||
keys(success: (keys: string[]) => void, error: () => void): void;
|
||||
/**
|
||||
* Removes a single stored item
|
||||
* @param reference {string}
|
||||
*/
|
||||
remove(reference: string, success: () => void, error: () => void): void;
|
||||
/**
|
||||
* Removes all stored values.
|
||||
*/
|
||||
clear(success: () => void, error: () => void): void;
|
||||
}
|
||||
|
||||
declare const NativeStorage: NativeStorageOriginal;
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
NativeStorage: NativeStorageOriginal;
|
||||
}
|
||||
}
|