Skip to content

Commit

Permalink
chore: improve message app
Browse files Browse the repository at this point in the history
  • Loading branch information
zensh committed Sep 10, 2024
1 parent b7d895f commit 05eb457
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
type ChannelInfoEx,
type MyMessageState
} from '$src/lib/stores/message'
import { sleep } from '$src/lib/utils/helper'
import { Avatar, getToastStore } from '@skeletonlabs/skeleton'
import { onMount } from 'svelte'
import { type Readable } from 'svelte/store'
Expand All @@ -20,20 +21,31 @@
export let channelId: string
const toastStore = getToastStore()
const { canister, id } = ChannelAPI.parseChannelParam(channelId)
let myState: MyMessageState
let myInfo: Readable<UserInfo>
let channelInfo: Readable<ChannelInfoEx>
let openSettings = false
function onCreateChannelHandler() {
let switching = false
async function onClickChannelSetting() {
if (!canister) return
switching = true
await Promise.all([
async () => {
// load latest channel info
channelInfo = await myState.loadChannelInfo(canister, id)
},
sleep(200)
])
openSettings = !openSettings
switching = false
}
onMount(() => {
const { abort } = toastRun(async (signal: AbortSignal) => {
const { canister, id } = ChannelAPI.parseChannelParam(channelId)
if (canister && !signal.aborted) {
if (canister) {
myState = await myMessageStateAsync()
myInfo = myState.info as Readable<UserInfo>
channelInfo = await myState.loadChannelInfo(canister, id)
Expand Down Expand Up @@ -78,7 +90,8 @@
type="button"
class="btn-icon"
title="Channel settings"
on:click={onCreateChannelHandler}
disabled={switching}
on:click={onClickChannelSetting}
><span>
{#if openSettings}
<IconClose />
Expand All @@ -92,7 +105,7 @@
{#if openSettings}
<ChannelSetting {myState} {myInfo} channelInfo={$channelInfo} />
{:else}
<ChannelMessages {myState} {myInfo} {channelInfo} />
<ChannelMessages {myState} {myInfo} channelInfo={$channelInfo} />
{/if}
{:else}
<div class="m-auto size-24 rounded-full *:size-24">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
export let myState: MyMessageState
export let myInfo: Readable<UserInfo>
export let channelInfo: Readable<ChannelInfoEx>
export let channelInfo: ChannelInfoEx
const toastStore = getToastStore()
const { canister, id } = $channelInfo
const { canister, id } = channelInfo
let messageFeed: Writable<MessageInfo[]> = writable([])
let latestMessage: Readable<MessageInfo | null>
Expand Down Expand Up @@ -117,29 +117,29 @@
const debouncedUpdateMyLastRead = debounce(async () => {
await myState.updateMyLastRead(canister, id, latestMessageId)
}, 10000)
}, 6000)
async function loadMessages(canister: Principal, id: number) {
channelAPI = await myState.api.channelAPI(canister)
dek = await myState.decryptChannelDEK($channelInfo)
latestMessage = await myState.loadLatestMessageStream(
canister,
id,
dek,
$channelInfo.latest_message_id
)
dek = await myState.decryptChannelDEK(channelInfo)
const prevMessages = await myState.loadPrevMessages(
canister,
id,
dek,
$channelInfo.latest_message_id
channelInfo.latest_message_id + 1
)
if (prevMessages.length > 0) {
messageFeed.update((prev) => [...prevMessages, ...prev])
}
latestMessage = await myState.loadLatestMessageStream(
canister,
id,
dek,
channelInfo.latest_message_id + 1
)
await tick()
debouncedUpdateMyLastRead()
debouncedUpdateMyLastRead.trigger()
Expand All @@ -149,6 +149,9 @@
onMount(() => {
const { abort } = toastRun(async (signal: AbortSignal) => {
if (!signal.aborted) {
if (!channelInfo._kek) {
channelInfo = await myState.refreshMyChannel(channelInfo)
}
await loadMessages(canister, id)
} else {
goto('/_/messages')
Expand All @@ -174,7 +177,7 @@

<div class="grid max-h-[calc(100dvh-140px)] grid-rows-[1fr_auto] bg-gray/5">
<!-- Conversation -->
<section bind:this={elemChat} class="space-y-4 overflow-y-auto p-4 pb-40">
<section bind:this={elemChat} class="space-y-4 overflow-y-auto p-4 pb-20">
{#each $messageFeed as msg (msg.id)}
{#if msg.created_by.compareTo(myState.principal) !== 'eq'}
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@
function onClickAdminExchangeKeys() {
adminExchangeKeysSubmitting = true
toastRun(async (signal: AbortSignal) => {
// fetch the latest ECDH request
channelInfo = await myState.refreshMyChannel(channelInfo)
await myState.adminExchangeKEK(channelInfo)
channelInfo = await myState.refreshMyChannel(channelInfo)
await loadMembers()
Expand Down Expand Up @@ -209,9 +211,8 @@
onMount(() => {
const { abort } = toastRun(async (signal: AbortSignal) => {
if (!signal.aborted) {
await loadMembers()
}
channelInfo = await myState.refreshMyChannel(channelInfo)
await loadMembers()
}, toastStore)
return abort
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
import { goto } from '$app/navigation'
import { page } from '$app/stores'
import { type UserInfo } from '$lib/canisters/message'
import { MyMessageState } from '$src/lib/stores/message'
import { Avatar } from '@skeletonlabs/skeleton'
import { type Readable } from 'svelte/store'
import ChannelDetail from './ChannelDetail.svelte'
import MyChannelList from './MyChannelList.svelte'
import ProfileDetail from './ProfileDetail.svelte'
export let myState: MyMessageState // force reactivity when 'myState' updated
export let myInfo: Readable<UserInfo>
function onMeHandler() {
Expand Down Expand Up @@ -60,7 +62,7 @@
<div
class="grid-row-[1fr] grid max-h-[calc(100dvh-76px)] items-start gap-6 rounded-tr-2xl bg-white"
>
<ProfileDetail userId={$myInfo.id} />
<ProfileDetail userId={myState.id} />
</div>
{/if}
</div>
Expand Down
10 changes: 2 additions & 8 deletions src/ic_panda_frontend/src/lib/components/messages/Home.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
type MyMessageState
} from '$src/lib/stores/message'
import { getModalStore, getToastStore } from '@skeletonlabs/skeleton'
import { getContext } from 'svelte'
import { type Readable } from 'svelte/store'
import UserRegisterModel from './UserRegisterModel.svelte'
Expand All @@ -16,7 +15,6 @@
const toastStore = getToastStore()
const modalStore = getModalStore()
const initState = getContext('InitState')
function getStartedHandler() {
toastRun(async () => {
Expand All @@ -29,9 +27,7 @@
type: 'component',
component: {
ref: UserRegisterModel,
props: {
initState: initState || null
}
props: {}
}
})
}
Expand All @@ -40,9 +36,7 @@
type: 'component',
component: {
ref: UserRegisterModel,
props: {
initState: initState || null
}
props: {}
}
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
type MyMessageState
} from '$src/lib/stores/message'
import { getModalStore, getToastStore } from '@skeletonlabs/skeleton'
import { onMount, setContext } from 'svelte'
import { onMount } from 'svelte'
import { type Readable } from 'svelte/store'
import Chat from './Chat.svelte'
import Home from './Home.svelte'
Expand All @@ -22,6 +22,7 @@
async function initState() {
myState = await myMessageStateAsync()
await myState.refreshState()
myInfo = myState.info
myInfo_ = myInfo as Readable<UserInfo>
if ($myInfo) {
Expand All @@ -41,8 +42,6 @@
}
}
setContext('InitState', initState)
onMount(() => {
const { abort } = toastRun(initState, toastStore)
return abort
Expand All @@ -60,7 +59,7 @@
</script>

{#if $myInfo}
<Chat myInfo={myInfo_} />
<Chat {myState} myInfo={myInfo_} />
{:else}
<Home {myState} {myInfo} />
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
const toastStore = getToastStore()
const keyId = encodeCBOR('ICPanda_Messages_Master_Key')
const PasswordExpire = 7 * 24 * 60 * 60 * 1000
const PasswordExpire = 14 * 24 * 60 * 60 * 1000
let validating = false
let submitting = false
Expand Down Expand Up @@ -51,7 +51,7 @@
)
if (masterKey.kind !== kind) {
processingTip = 'Migrate keys...'
processingTip = 'Migrate encrypted keys to ICP chain ...'
await myState.migrateKeys()
} else {
await myState.initStaticECDHKey()
Expand Down Expand Up @@ -164,7 +164,7 @@
{/if}
<label class="mt-2 flex items-center">
<input class="checkbox" type="checkbox" bind:checked={cachedPassword} />
<p class="ml-2 text-sm text-gray/50">Cache password for 7 days</p>
<p class="ml-2 text-sm text-gray/50">Cache password for 14 days</p>
</label>
</form>
<footer class="m-auto !mt-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
} from '$src/lib/stores/message'
import { Principal } from '@dfinity/principal'
import { Avatar, getModalStore, getToastStore } from '@skeletonlabs/skeleton'
import { getContext, onMount } from 'svelte'
import { onMount } from 'svelte'
import { type Readable } from 'svelte/store'
import ProfileEditModel from './ProfileEditModel.svelte'
import UserRegisterModel from './UserRegisterModel.svelte'
Expand All @@ -21,7 +21,6 @@
const toastStore = getToastStore()
const modalStore = getModalStore()
const initState = getContext('InitState')
let myID: Principal
let myState: MyMessageState
Expand Down Expand Up @@ -79,9 +78,7 @@
type: 'component',
component: {
ref: UserRegisterModel,
props: {
initState: initState || null
}
props: {}
}
})
}
Expand All @@ -95,14 +92,16 @@
onfinally((info) => {
if (!info) {
setTimeout(() => goto('/_/messages'), 2000)
} else if (info.id.compareTo(myID) == 'eq' && info.username.length == 0) {
} else if (
info.id.compareTo(myID) == 'eq' &&
info.username.length == 0 &&
info.created_at < BigInt(Date.now() - 180 * 1000)
) {
modalStore.trigger({
type: 'component',
component: {
ref: UserRegisterModel,
props: {
initState: initState || null
}
props: {}
}
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
myMessageStateAsync,
type MyMessageState
} from '$src/lib/stores/message'
import { sleep } from '$src/lib/utils/helper'
import { Principal } from '@dfinity/principal'
import { getModalStore, getToastStore } from '@skeletonlabs/skeleton'
import debounce from 'debounce'
import { onDestroy, onMount, type SvelteComponent } from 'svelte'
import { type Readable } from 'svelte/store'
import PasswordModel from './PasswordModel.svelte'
const usernameReg = /^[a-z0-9][a-z0-9_]{0,19}$/i
const toastStore = getToastStore()
Expand All @@ -29,7 +31,6 @@
// Props
/** Exposes parent props to this component. */
export let parent: SvelteComponent
export let initState: null | (() => Promise<void>) = null
const messageCanisterPrincipal = Principal.fromText(MESSAGE_CANISTER_ID)
Expand Down Expand Up @@ -83,15 +84,28 @@
if (!usernameInput) {
result = await myState.api.update_my_name(nameInput)
await sleep(1000)
await myState.api.refreshMyInfo()
} else {
await tokenLedgerAPI.ensureAllowance(messageCanisterPrincipal, amount)
result = await myState.api.register_username(usernameInput, nameInput)
await sleep(1000)
await myState.refreshState()
}
await myState.api.refreshMyInfo()
if (initState) {
const mk = await myState.masterKey()
if (!mk || !mk.isOpened() || myState.masterKeyKind() !== mk.kind) {
modalStore.close()
initState()
modalStore.trigger({
type: 'component',
component: {
ref: PasswordModel,
props: {
myState: myState,
masterKey: mk
}
}
})
} else {
setTimeout(async () => {
modalStore.close()
Expand Down
Loading

0 comments on commit 05eb457

Please sign in to comment.