From 521dcb38e18e5f54a0f06b31f199d278201d4647 Mon Sep 17 00:00:00 2001 From: Bojan Mojsilovic Date: Wed, 7 Feb 2024 14:41:27 +0100 Subject: [PATCH] Get mobile app releases from the server --- src/Router.tsx | 11 +++++++-- src/constants.ts | 1 + src/contexts/NotificationsContext.tsx | 13 +++++++--- src/contexts/SettingsContext.tsx | 34 ++++++++++++++++++++++++++- src/lib/releases.ts | 9 +++++++ src/pages/Downloads.module.scss | 2 ++ src/pages/Downloads.tsx | 28 ++++++++++++++++------ 7 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 src/lib/releases.ts diff --git a/src/Router.tsx b/src/Router.tsx index b38378d..972c4db 100644 --- a/src/Router.tsx +++ b/src/Router.tsx @@ -1,5 +1,5 @@ -import { Component, createResource, lazy } from 'solid-js'; -import { Routes, Route, Navigate, RouteDataFuncArgs } from "@solidjs/router"; +import { Component, createEffect, createResource, lazy } from 'solid-js'; +import { Routes, Route, Navigate, RouteDataFuncArgs, useLocation } from "@solidjs/router"; import { PrimalWindow } from './types/primal'; import { fetchKnownProfiles } from './lib/profile'; @@ -60,6 +60,7 @@ const Router: Component = () => { const media = useMediaContext(); const notifications = useNotificationsContext(); const search = useSearchContext(); + const locations = useLocation(); if (isDev) { primalWindow.primal = { @@ -88,6 +89,12 @@ const Router: Component = () => { return profiles; } + createEffect(() => { + if (locations.pathname) { + settings?.actions.refreshMobileReleases(); + } + }); + return ( <> diff --git a/src/constants.ts b/src/constants.ts index 8e10d7e..15f30e5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -126,6 +126,7 @@ export enum Kind { MediaInfo = 10_000_119, Upload = 10_000_120, Uploaded = 10_000_121, + Releases = 10_000_124, ImportResponse = 10_000_127, LinkMetadata = 10_000_128, FilteringReason = 10_000_131, diff --git a/src/contexts/NotificationsContext.tsx b/src/contexts/NotificationsContext.tsx index 625e590..70559cf 100644 --- a/src/contexts/NotificationsContext.tsx +++ b/src/contexts/NotificationsContext.tsx @@ -1,5 +1,5 @@ import { createStore } from "solid-js/store"; -import { andVersion, andRD, iosVersion, iosRD, Kind, today } from "../constants"; +import { andRD, andVersion, iosRD, iosVersion, Kind } from "../constants"; import { createContext, createEffect, @@ -22,6 +22,7 @@ import { APP_ID } from "../App"; import { getLastSeen, subscribeToNotificationStats, unsubscribeToNotificationStats } from "../lib/notifications"; import { useAccountContext } from "./AccountContext"; import { timeNow } from "../utils"; +import { useSettingsContext } from "./SettingsContext"; export type NotificationsContextStore = { notificationCount: number, @@ -47,9 +48,12 @@ export const NotificationsContext = createContext(); export const NotificationsProvider = (props: { children: ContextChildren }) => { const account = useAccountContext(); + const settings = useSettingsContext(); const subid = `notif_stats_${APP_ID}`; + const today = () => (new Date()).getTime(); + // ACTIONS -------------------------------------- const subToNotificationStats = () => { @@ -65,13 +69,16 @@ export const NotificationsProvider = (props: { children: ContextChildren }) => { const iosDownload = localStorage.getItem('iosDownload'); 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; - if (iosDownload !== iosVersion && today > iosRD) { + if (iosDownload !== ios.version && today() > (new Date(ios.date)).getTime()) { count++; } - if (andDownload !== andVersion && today > andRD) { + if (andDownload !== and.version && today() > (new Date(and.date)).getTime()) { count++; } diff --git a/src/contexts/SettingsContext.tsx b/src/contexts/SettingsContext.tsx index de73b6e..d5894ed 100644 --- a/src/contexts/SettingsContext.tsx +++ b/src/contexts/SettingsContext.tsx @@ -1,6 +1,6 @@ import { createStore } from "solid-js/store"; 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 { createContext, createEffect, @@ -36,6 +36,12 @@ import { APP_ID } from "../App"; import { useIntl } from "@cookbook/solid-intl"; import { hexToNpub } from "../lib/keys"; 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 = { locale: string, @@ -50,6 +56,7 @@ export type SettingsContextStore = { notificationSettings: Record, applyContentModeration: boolean, contentModeration: ContentModeration[], + mobileReleases: MobileReleases, actions: { setTheme: (theme: PrimalTheme | null) => void, addAvailableFeed: (feed: PrimalFeed, addToTop?: boolean) => void, @@ -66,6 +73,7 @@ export type SettingsContextStore = { restoreDefaultFeeds: () => void, setApplyContentModeration: (flag: boolean) => void, modifyContentModeration: (name: string, content?: boolean, trending?: boolean) => void, + refreshMobileReleases: () => void, } } @@ -82,6 +90,10 @@ export const initialData = { notificationSettings: { ...defaultNotificationSettings }, applyContentModeration: true, 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); } + 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 ------------------------------ const onMessage = (event: MessageEvent) => { @@ -521,6 +551,7 @@ export const SettingsProvider = (props: { children: ContextChildren }) => { // when waiting for pubkey (like when reloading a page). const storedTheme = localStorage.getItem('theme'); setThemeByName(storedTheme, true); + refreshMobileReleases(); }); @@ -629,6 +660,7 @@ export const SettingsProvider = (props: { children: ContextChildren }) => { updateNotificationSettings, setApplyContentModeration, modifyContentModeration, + refreshMobileReleases, }, }); diff --git a/src/lib/releases.ts b/src/lib/releases.ts new file mode 100644 index 0000000..b304935 --- /dev/null +++ b/src/lib/releases.ts @@ -0,0 +1,9 @@ +import { sendMessage } from "../sockets" + +export const getMobileReleases = (subid: string) => { + sendMessage(JSON.stringify([ + "REQ", + subid, + {cache: ["get_app_releases"]}, + ])) +} diff --git a/src/pages/Downloads.module.scss b/src/pages/Downloads.module.scss index 02adfdb..52cab4c 100644 --- a/src/pages/Downloads.module.scss +++ b/src/pages/Downloads.module.scss @@ -91,6 +91,7 @@ font-size: 14px; font-weight: 400; line-height: 14px; + margin-top: 4px; >div:first-child { display: flex; @@ -142,6 +143,7 @@ font-size: 14px; font-weight: 400; line-height: 14px; + margin-top: 4px; >div:first-child { display: flex; diff --git a/src/pages/Downloads.tsx b/src/pages/Downloads.tsx index d1887c6..d93aa1e 100644 --- a/src/pages/Downloads.tsx +++ b/src/pages/Downloads.tsx @@ -15,22 +15,32 @@ import styles from './Downloads.module.scss'; import { downloads as t } from '../translations'; import { useIntl } from '@cookbook/solid-intl'; 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 PageCaption from '../components/PageCaption/PageCaption'; import PageTitle from '../components/PageTitle/PageTitle'; +import { useSettingsContext } from '../contexts/SettingsContext'; const Downloads: Component = () => { 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(() => { - if (today > iosRD) { - localStorage.setItem('iosDownload', iosVersion); + if (today() > iosRD()) { + localStorage.setItem('iosDownload', iosVersion()); } - if (today > andRD) { - localStorage.setItem('andDownload', andVersion); + if (today() > andRD()) { + localStorage.setItem('andDownload', andVersion()); } }); @@ -42,6 +52,10 @@ const Downloads: Component = () => { }).format(date); } + const stringToDate = (dateString: string) => { + return (new Date(dateString)).getTime(); + } + return (
{
- {displayDate(iosRD).toLowerCase()} | {intl.formatMessage(t.build)} {iosVersion} + {displayDate(iosRD()).toLowerCase()} | {intl.formatMessage(t.build)} {iosVersion()}
@@ -139,7 +153,7 @@ const Downloads: Component = () => {
- {displayDate(andRD).toLowerCase()} | {intl.formatMessage(t.build)} {andVersion} + {displayDate(andRD()).toLowerCase()} | {intl.formatMessage(t.build)} {andVersion()}