Get mobile app releases from the server

This commit is contained in:
Bojan Mojsilovic 2024-02-07 14:41:27 +01:00
parent d431187cff
commit 521dcb38e1
7 changed files with 85 additions and 13 deletions

View File

@ -1,5 +1,5 @@
import { Component, createResource, lazy } from 'solid-js'; import { Component, createEffect, createResource, lazy } from 'solid-js';
import { Routes, Route, Navigate, RouteDataFuncArgs } from "@solidjs/router"; import { Routes, Route, Navigate, RouteDataFuncArgs, useLocation } from "@solidjs/router";
import { PrimalWindow } from './types/primal'; import { PrimalWindow } from './types/primal';
import { fetchKnownProfiles } from './lib/profile'; import { fetchKnownProfiles } from './lib/profile';
@ -60,6 +60,7 @@ const Router: Component = () => {
const media = useMediaContext(); const media = useMediaContext();
const notifications = useNotificationsContext(); const notifications = useNotificationsContext();
const search = useSearchContext(); const search = useSearchContext();
const locations = useLocation();
if (isDev) { if (isDev) {
primalWindow.primal = { primalWindow.primal = {
@ -88,6 +89,12 @@ const Router: Component = () => {
return profiles; return profiles;
} }
createEffect(() => {
if (locations.pathname) {
settings?.actions.refreshMobileReleases();
}
});
return ( return (
<> <>
<Routes> <Routes>

View File

@ -126,6 +126,7 @@ export enum Kind {
MediaInfo = 10_000_119, MediaInfo = 10_000_119,
Upload = 10_000_120, Upload = 10_000_120,
Uploaded = 10_000_121, Uploaded = 10_000_121,
Releases = 10_000_124,
ImportResponse = 10_000_127, ImportResponse = 10_000_127,
LinkMetadata = 10_000_128, LinkMetadata = 10_000_128,
FilteringReason = 10_000_131, FilteringReason = 10_000_131,

View File

@ -1,5 +1,5 @@
import { createStore } from "solid-js/store"; import { createStore } from "solid-js/store";
import { andVersion, andRD, iosVersion, iosRD, Kind, today } from "../constants"; import { andRD, andVersion, iosRD, iosVersion, Kind } from "../constants";
import { import {
createContext, createContext,
createEffect, createEffect,
@ -22,6 +22,7 @@ import { APP_ID } from "../App";
import { getLastSeen, subscribeToNotificationStats, unsubscribeToNotificationStats } from "../lib/notifications"; import { getLastSeen, subscribeToNotificationStats, unsubscribeToNotificationStats } from "../lib/notifications";
import { useAccountContext } from "./AccountContext"; import { useAccountContext } from "./AccountContext";
import { timeNow } from "../utils"; import { timeNow } from "../utils";
import { useSettingsContext } from "./SettingsContext";
export type NotificationsContextStore = { export type NotificationsContextStore = {
notificationCount: number, notificationCount: number,
@ -47,9 +48,12 @@ export const NotificationsContext = createContext<NotificationsContextStore>();
export const NotificationsProvider = (props: { children: ContextChildren }) => { export const NotificationsProvider = (props: { children: ContextChildren }) => {
const account = useAccountContext(); const account = useAccountContext();
const settings = useSettingsContext();
const subid = `notif_stats_${APP_ID}`; const subid = `notif_stats_${APP_ID}`;
const today = () => (new Date()).getTime();
// ACTIONS -------------------------------------- // ACTIONS --------------------------------------
const subToNotificationStats = () => { const subToNotificationStats = () => {
@ -65,13 +69,16 @@ export const NotificationsProvider = (props: { children: ContextChildren }) => {
const iosDownload = localStorage.getItem('iosDownload'); const iosDownload = localStorage.getItem('iosDownload');
const andDownload = localStorage.getItem('andDownload'); const andDownload = localStorage.getItem('andDownload');
const ios = settings?.mobileReleases.ios || { date: iosRD, version: iosVersion};
const and = settings?.mobileReleases.android || { date: andRD, version: andVersion};
let count = 0; let count = 0;
if (iosDownload !== iosVersion && today > iosRD) { if (iosDownload !== ios.version && today() > (new Date(ios.date)).getTime()) {
count++; count++;
} }
if (andDownload !== andVersion && today > andRD) { if (andDownload !== and.version && today() > (new Date(and.date)).getTime()) {
count++; count++;
} }

View File

@ -1,6 +1,6 @@
import { createStore } from "solid-js/store"; import { createStore } from "solid-js/store";
import { useToastContext } from "../components/Toaster/Toaster"; import { useToastContext } from "../components/Toaster/Toaster";
import { contentScope, defaultContentModeration, defaultFeeds, defaultNotificationSettings, defaultZap, defaultZapOptions, nostrHighlights, themes, trendingFeed, trendingScope } from "../constants"; import { andRD, andVersion, contentScope, defaultContentModeration, defaultFeeds, defaultNotificationSettings, defaultZap, defaultZapOptions, iosRD, iosVersion, nostrHighlights, themes, trendingFeed, trendingScope } from "../constants";
import { import {
createContext, createContext,
createEffect, createEffect,
@ -36,6 +36,12 @@ import { APP_ID } from "../App";
import { useIntl } from "@cookbook/solid-intl"; import { useIntl } from "@cookbook/solid-intl";
import { hexToNpub } from "../lib/keys"; import { hexToNpub } from "../lib/keys";
import { settings as t } from "../translations"; import { settings as t } from "../translations";
import { getMobileReleases } from "../lib/releases";
export type MobileReleases = {
ios: { date: string, version: string },
android: { date: string, version: string },
}
export type SettingsContextStore = { export type SettingsContextStore = {
locale: string, locale: string,
@ -50,6 +56,7 @@ export type SettingsContextStore = {
notificationSettings: Record<string, boolean>, notificationSettings: Record<string, boolean>,
applyContentModeration: boolean, applyContentModeration: boolean,
contentModeration: ContentModeration[], contentModeration: ContentModeration[],
mobileReleases: MobileReleases,
actions: { actions: {
setTheme: (theme: PrimalTheme | null) => void, setTheme: (theme: PrimalTheme | null) => void,
addAvailableFeed: (feed: PrimalFeed, addToTop?: boolean) => void, addAvailableFeed: (feed: PrimalFeed, addToTop?: boolean) => void,
@ -66,6 +73,7 @@ export type SettingsContextStore = {
restoreDefaultFeeds: () => void, restoreDefaultFeeds: () => void,
setApplyContentModeration: (flag: boolean) => void, setApplyContentModeration: (flag: boolean) => void,
modifyContentModeration: (name: string, content?: boolean, trending?: boolean) => void, modifyContentModeration: (name: string, content?: boolean, trending?: boolean) => void,
refreshMobileReleases: () => void,
} }
} }
@ -82,6 +90,10 @@ export const initialData = {
notificationSettings: { ...defaultNotificationSettings }, notificationSettings: { ...defaultNotificationSettings },
applyContentModeration: true, applyContentModeration: true,
contentModeration: [...defaultContentModeration], contentModeration: [...defaultContentModeration],
mobileReleases: {
ios: { date: `${iosRD}`, version: iosVersion },
android: { date: `${andRD}`, version: andVersion },
},
}; };
@ -496,6 +508,24 @@ export const SettingsProvider = (props: { children: ContextChildren }) => {
pubkey && getSettings(pubkey, subid); pubkey && getSettings(pubkey, subid);
} }
const refreshMobileReleases = () => {
const subid = `mobile_releases_${APP_ID}`;
const unsub = subscribeTo(subid, async (type, subId, content) => {
if (type === 'EVENT') {
const releases = JSON.parse(content?.content || '{}') as MobileReleases;
updateStore('mobileReleases', () => ({ ...releases }));
}
if (type === 'EOSE') {
unsub();
}
});
getMobileReleases(subid);
};
// SOCKET HANDLERS ------------------------------ // SOCKET HANDLERS ------------------------------
const onMessage = (event: MessageEvent) => { const onMessage = (event: MessageEvent) => {
@ -521,6 +551,7 @@ export const SettingsProvider = (props: { children: ContextChildren }) => {
// when waiting for pubkey (like when reloading a page). // when waiting for pubkey (like when reloading a page).
const storedTheme = localStorage.getItem('theme'); const storedTheme = localStorage.getItem('theme');
setThemeByName(storedTheme, true); setThemeByName(storedTheme, true);
refreshMobileReleases();
}); });
@ -629,6 +660,7 @@ export const SettingsProvider = (props: { children: ContextChildren }) => {
updateNotificationSettings, updateNotificationSettings,
setApplyContentModeration, setApplyContentModeration,
modifyContentModeration, modifyContentModeration,
refreshMobileReleases,
}, },
}); });

9
src/lib/releases.ts Normal file
View File

@ -0,0 +1,9 @@
import { sendMessage } from "../sockets"
export const getMobileReleases = (subid: string) => {
sendMessage(JSON.stringify([
"REQ",
subid,
{cache: ["get_app_releases"]},
]))
}

View File

@ -91,6 +91,7 @@
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 14px; line-height: 14px;
margin-top: 4px;
>div:first-child { >div:first-child {
display: flex; display: flex;
@ -142,6 +143,7 @@
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 14px; line-height: 14px;
margin-top: 4px;
>div:first-child { >div:first-child {
display: flex; display: flex;

View File

@ -15,22 +15,32 @@ import styles from './Downloads.module.scss';
import { downloads as t } from '../translations'; import { downloads as t } from '../translations';
import { useIntl } from '@cookbook/solid-intl'; import { useIntl } from '@cookbook/solid-intl';
import StickySidebar from '../components/StickySidebar/StickySidebar'; import StickySidebar from '../components/StickySidebar/StickySidebar';
import { andVersion, andRD, iosVersion, iosRD, today, appStoreLink, playstoreLink, apkLink } from '../constants'; import { appStoreLink, playstoreLink, apkLink } from '../constants';
import ExternalLink from '../components/ExternalLink/ExternalLink'; import ExternalLink from '../components/ExternalLink/ExternalLink';
import PageCaption from '../components/PageCaption/PageCaption'; import PageCaption from '../components/PageCaption/PageCaption';
import PageTitle from '../components/PageTitle/PageTitle'; import PageTitle from '../components/PageTitle/PageTitle';
import { useSettingsContext } from '../contexts/SettingsContext';
const Downloads: Component = () => { const Downloads: Component = () => {
const intl = useIntl(); const intl = useIntl();
const settings = useSettingsContext();
const iosRD = () => stringToDate(settings?.mobileReleases.ios.date || '0');
const iosVersion = () => settings?.mobileReleases.ios.version || '0';
const andRD = () => stringToDate(settings?.mobileReleases.android.date || '0');
const andVersion = () => settings?.mobileReleases.android.version || '0';
const today = () => (new Date()).getTime();
onMount(() => { onMount(() => {
if (today > iosRD) { if (today() > iosRD()) {
localStorage.setItem('iosDownload', iosVersion); localStorage.setItem('iosDownload', iosVersion());
} }
if (today > andRD) { if (today() > andRD()) {
localStorage.setItem('andDownload', andVersion); localStorage.setItem('andDownload', andVersion());
} }
}); });
@ -42,6 +52,10 @@ const Downloads: Component = () => {
}).format(date); }).format(date);
} }
const stringToDate = (dateString: string) => {
return (new Date(dateString)).getTime();
}
return ( return (
<div class={styles.downloadsContainer}> <div class={styles.downloadsContainer}>
<Wormhole <Wormhole
@ -117,7 +131,7 @@ const Downloads: Component = () => {
<div class={styles.buidDetails}> <div class={styles.buidDetails}>
<div> <div>
{displayDate(iosRD).toLowerCase()} | {intl.formatMessage(t.build)} {iosVersion} {displayDate(iosRD()).toLowerCase()} | {intl.formatMessage(t.build)} {iosVersion()}
</div> </div>
</div> </div>
@ -139,7 +153,7 @@ const Downloads: Component = () => {
<div class={styles.buidDetails}> <div class={styles.buidDetails}>
<div> <div>
{displayDate(andRD).toLowerCase()} | {intl.formatMessage(t.build)} {andVersion} {displayDate(andRD()).toLowerCase()} | {intl.formatMessage(t.build)} {andVersion()}
</div> </div>
</div> </div>