Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.maroonrides.maroonrides;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
import java.io.File;

// for moving react natives sqlite db to capacitor layer
@CapacitorPlugin(name = "LegacyPrefs")
public class LegacyPrefsPlugin extends Plugin {

private static final String DATABASE_NAME = "RKStorage";
private static final String TABLE_NAME = "catalystLocalStorage";
private static final String KEY_COLUMN = "key";
private static final String VALUE_COLUMN = "value";

@PluginMethod
public void getLegacyPrefs(PluginCall call) {
JSObject entries = new JSObject();
JSObject result = new JSObject();
result.put("available", false);

File database = getContext().getDatabasePath(DATABASE_NAME);
if (!database.exists()) {
result.put("entries", entries);
call.resolve(result);
return;
}

SQLiteDatabase db = null;
Cursor cursor = null;

try {
db = SQLiteDatabase.openDatabase(database.getPath(), null, SQLiteDatabase.OPEN_READONLY);
cursor = db.query(TABLE_NAME, new String[] { KEY_COLUMN, VALUE_COLUMN }, null, null, null, null, null);

while (cursor.moveToNext()) {
String key = cursor.getString(0);
String value = cursor.getString(1);
if (key != null && value != null) {
entries.put(key, value);
}
}

result.put("available", true);
} catch (Exception e) {
// oh well resave your prefs
result.put("available", false);
} finally {
if (cursor != null) {
cursor.close();
}
if (db != null) {
db.close();
}
}

result.put("entries", entries);
call.resolve(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,34 @@
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
// register before super.onCreate() helped load properly
registerPlugin(LegacyPrefsPlugin.class);

super.onCreate(savedInstanceState);

// DANGER: Forces the native Java layer to accept expired/invalid certs
bypassNativeSSLChecks();
}

private void bypassNativeSSLChecks() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}

public void checkClientTrusted(X509Certificate[] certs, String authType) {
}

public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());

// Apply trust-all logic globally to native requests
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
Expand Down
12 changes: 9 additions & 3 deletions src/lib/components/ui/map/Map.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
let isMounted = $state(false);
let isLoaded = $state(false);
let isStyleLoaded = $state(false);
let initialStyleApplied = false;
let initialStyleApplied = $state(false);
let appliedStyle: MapStyleOption | null = null;
let styleTimeoutId: ReturnType<typeof setTimeout> | null = null;

const mapStyles = $derived({
Expand Down Expand Up @@ -91,9 +92,11 @@

bounds = new MapLibreGL.LngLatBounds([h.minLon, h.minLat], [h.maxLon, h.maxLat]);

appliedStyle = currentStyle;

const mapInstance = new MapLibreGL.Map({
container: mapContainer,
style: currentStyle,
style: appliedStyle,
renderWorldCopies: false,
// TODO move attribution elsewhere
attributionControl: false,
Expand Down Expand Up @@ -137,12 +140,15 @@
$effect(() => {
const style = currentStyle;

if (!map || !initialStyleApplied) {
// making this a state \/ bc prefs loaded like half a sec later
// where first load on update desyncs color from prefs
if (!map || !initialStyleApplied || style === appliedStyle) {
return;
}

untrack(() => {
isStyleLoaded = false;
appliedStyle = style;
// Diff mode helps reuse existing layers for better performance
map!.setStyle(style, { diff: false }); // Changed to false - full style reload is more reliable for theme changes
});
Expand Down
8 changes: 6 additions & 2 deletions src/lib/managers/frontpage.manager.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ class FrontPageManager {
selectedTab = $state('all');

constructor() {
this.loadDefaultGroup(); //only set once here since it only applies on-open
this.loadFavorites();
this.load();
}

async load() {
await this.loadDefaultGroup(); //only set once here since it only applies on-open
await this.loadFavorites();
}

async loadDefaultGroup() {
Expand Down
38 changes: 38 additions & 0 deletions src/lib/utils/legacy-migration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Capacitor, registerPlugin } from '@capacitor/core';
import { Directory, Filesystem } from '@capacitor/filesystem';

// for android react native move
interface LegacyPrefsPlugin {
getLegacyPrefs(): Promise<{ available: boolean; entries: Record<string, string> }>;
}
const LegacyPrefs = registerPlugin<LegacyPrefsPlugin>('LegacyPrefs');

export async function readLegacyPrefs(): Promise<Record<string, string> | null> {
const platform = Capacitor.getPlatform();

if (platform === 'ios') {
try {
const iosRCTPrefs = await Filesystem.readFile({
directory: Directory.Library,
path: 'Application Support/com.bwees.reveille-rides/RCTAsyncLocalStorage_V1/manifest.json',
});

return JSON.parse(atob(iosRCTPrefs.data as string));
} catch (e) {
console.log('Error migrating iOS RCTAsyncLocalStorage_V1 manifest:', e);
return null;
}
}

if (platform === 'android') {
try {
const { available, entries } = await LegacyPrefs.getLegacyPrefs();
return available ? entries : null;
} catch (e) {
console.log('Error migrating Android RKStorage database:', e);
return null;
}
}

return null;
}
74 changes: 39 additions & 35 deletions src/lib/utils/prefs.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,49 @@
import { Capacitor } from '@capacitor/core';
import { Directory, Filesystem } from '@capacitor/filesystem';
import { Preferences } from '@capacitor/preferences';
import { setMode } from 'mode-watcher';
import { readLegacyPrefs } from './legacy-migration';
import { modeStorageKey, setMode } from 'mode-watcher';

export async function migratePrefs() {
const currentVersion = Number((await Preferences.get({ key: 'version' })).value ?? 0);

if (currentVersion < 1) {
// initial iOS migration
if (Capacitor.getPlatform() === 'ios') {
try {
const iosRCTPrefs = await Filesystem.readFile({
directory: Directory.Library,
path: 'Application Support/com.bwees.reveille-rides/RCTAsyncLocalStorage_V1/manifest.json',
});
export const PREFS_VERSION = 2;
export async function importLegacyPrefs(
legacy: Record<string, string | null>,
{ fillOnly = false }: { fillOnly?: boolean } = {},
) {
const favorites = legacy['favorites'];
if (favorites) {
const current = (await Preferences.get({ key: 'favorites' })).value;
const currentIsEmpty = !current || current === '[]';

const manifest = JSON.parse(atob(iosRCTPrefs.data as string));
if (!fillOnly || currentIsEmpty) {
await Preferences.set({ key: 'favorites', value: favorites });
}
}

await Preferences.set({
key: 'favorites',
value: manifest['favorites'] ?? '[]',
});
// rn stored the default group as an index
const defaultGroup = legacy['default-group'] === '1' ? 'favorites' : 'all';
const currentGroup = (await Preferences.get({ key: 'defaultGroup' })).value;

await Preferences.set({
key: 'defaultGroup',
value: manifest['default-group'] ?? '0',
});
if (!fillOnly || !currentGroup || currentGroup === 'all') {
await Preferences.set({ key: 'defaultGroup', value: defaultGroup });
}

// Theme watcher handles its own saving of theme preference
// just migrate the old app preference over.
let mode = 'system';
if (manifest['app-theme'] === '1') {
mode = 'light';
} else if (manifest['app-theme'] === '2') {
mode = 'dark';
}
setMode(mode as 'system' | 'light' | 'dark');
} catch (e) {
console.log('Error migrating iOS RCTAsyncLocalStorage_V1 manifest:', e);
}
const userPickedMode = localStorage.getItem(modeStorageKey.current) !== null;
if (!fillOnly || !userPickedMode) {
let mode = 'system';
if (legacy['app-theme'] === '1') {
mode = 'light';
} else if (legacy['app-theme'] === '2') {
mode = 'dark';
}
setMode(mode as 'system' | 'light' | 'dark');
}
}

export async function migratePrefs() {
const currentVersion = Number((await Preferences.get({ key: 'version' })).value ?? 0);
if (currentVersion >= PREFS_VERSION) return; // explicit flow

if (currentVersion < 1) {
const legacy = await readLegacyPrefs();
if (legacy) await importLegacyPrefs(legacy);

console.log('Preferences migrated to version 1');
await Preferences.set({ key: 'version', value: '1' });
Expand Down
4 changes: 3 additions & 1 deletion src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import ThemeWatcher from '$lib/components/ThemeWatcher.svelte';
import Map from '$lib/components/ui/map/Map.svelte';
import MapControls from '$lib/components/ui/map/MapControls.svelte';
import { frontPageManager } from '$lib/managers/frontpage.manager.svelte';
import { mapManager } from '$lib/managers/map.manager.svelte';
import { installInterceptor } from '$lib/utils/interceptor';
import { migratePrefs } from '$lib/utils/prefs';
Expand All @@ -21,7 +22,8 @@
});

onMount(async () => {
migratePrefs();
await migratePrefs(); //sync to reduce some ui flickering when states change
await frontPageManager.load();
});

installInterceptor();
Expand Down
Loading