From 6daa515d19933f0244ad8d1fd1b89b385d6c1083 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Sun, 11 Jun 2023 20:37:34 -0600 Subject: [PATCH] load feed of give records on home screen --- project.task.yaml | 4 +- src/components/InfiniteScroll.vue | 2 + src/db/index.ts | 4 +- src/libs/endorserServer.ts | 30 ++++ src/router/index.ts | 30 ++-- src/views/AccountViewView.vue | 3 +- src/views/HomeView.vue | 228 +++++++++++++++++++++++++++++- src/views/NewEditProjectView.vue | 6 +- src/views/StatisticsView.vue | 1 + 9 files changed, 285 insertions(+), 23 deletions(-) diff --git a/project.task.yaml b/project.task.yaml index 466b8c5..dbf4bbb 100644 --- a/project.task.yaml +++ b/project.task.yaml @@ -31,7 +31,9 @@ - Ensure each action sent to the server has a confirmation. -- discover screen +- Feed screen + - 01 save the feed in settings storage + - .5 add user-specific data - .5 customize favicon - .5 make advanced features harder to access; advanced build? diff --git a/src/components/InfiniteScroll.vue b/src/components/InfiniteScroll.vue index 2afdb9e..d973694 100644 --- a/src/components/InfiniteScroll.vue +++ b/src/components/InfiniteScroll.vue @@ -14,6 +14,7 @@ export default class InfiniteScroll extends Vue { readonly distance!: number; private observer!: IntersectionObserver; + // 'mounted' hook runs after initial render mounted() { const options = { root: this.$refs.scrollContainer as HTMLElement, @@ -24,6 +25,7 @@ export default class InfiniteScroll extends Vue { this.observer.observe(this.$refs.sentinel as HTMLElement); } + // 'beforeUnmount' hook runs before unmounting the component beforeUnmount() { this.observer.disconnect(); } diff --git a/src/db/index.ts b/src/db/index.ts index 24ca885..58bd231 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -44,8 +44,8 @@ const NonsensitiveSchemas = Object.assign({}, ContactsSchema, SettingsSchema); /** * Create password and place password in localStorage. * - * It's good practice to keep the data encrypted at rest, even if the secret - * is stored next to the app. + * It's good practice to keep the data encrypted at rest, so we'll do that even + * if the secret is stored right next to the app. */ const secret = localStorage.getItem("secret") || Encryption.createRandomEncryptionKey(); diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts index 227577f..20e04a6 100644 --- a/src/libs/endorserServer.ts +++ b/src/libs/endorserServer.ts @@ -47,3 +47,33 @@ export interface RegisterVerifiableCredential { object: string; recipient: { identifier: string }; } + +// This is used to check for hidden info. +// See https://github.com/trentlarson/endorser-ch/blob/0cb626f803028e7d9c67f095858a9fc8542e3dbd/server/api/services/util.js#L6 +const HIDDEN_DID = "did:none:HIDDEN"; + +const UNKNOWN_ENTITY = "Someone Unknown"; +const UNKNOWN_VISIBLE = "Someone Unnamed"; + +export function isHiddenDid(did) { + return did === HIDDEN_DID; +} + +/** + always returns text, maybe UNNAMED_VISIBLE or UNKNOWN_ENTITY + **/ +export function didInfo(did, identifiers, contacts) { + const myId = R.find((i) => i.did === did, identifiers); + if (myId) { + return "You"; + } else { + const contact = R.find((c) => c.did === did, contacts); + if (contact) { + return contact.name || "(no name)"; + } else if (isHiddenDid(did)) { + return UNKNOWN_ENTITY; + } else { + return UNKNOWN_VISIBLE; + } + } +} diff --git a/src/router/index.ts b/src/router/index.ts index d7fd253..28db091 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,21 +1,29 @@ import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; import { accountsDB } from "@/db"; +/** + * + * @param to :RouteLocationNormalized + * @param from :RouteLocationNormalized + * @param next :NavigationGuardNext + */ +const enterOrStart = async (to, from, next) => { + await accountsDB.open(); + const num_accounts = await accountsDB.accounts.count(); + if (num_accounts > 0) { + next(); + } else { + next({ name: "start" }); + } +}; + const routes: Array = [ { path: "/", name: "home", component: () => - import(/* webpackChunkName: "start" */ "../views/DiscoverView.vue"), - beforeEnter: async (to, from, next) => { - await accountsDB.open(); - const num_accounts = await accountsDB.accounts.count(); - if (num_accounts > 0) { - next(); - } else { - next({ name: "start" }); - } - }, + import(/* webpackChunkName: "home" */ "../views/HomeView.vue"), + beforeEnter: enterOrStart, }, { path: "/about", @@ -28,6 +36,7 @@ const routes: Array = [ name: "account", component: () => import(/* webpackChunkName: "account" */ "../views/AccountViewView.vue"), + beforeEnter: enterOrStart, }, { path: "/confirm-contact", @@ -58,6 +67,7 @@ const routes: Array = [ name: "contacts", component: () => import(/* webpackChunkName: "contacts" */ "../views/ContactsView.vue"), + beforeEnter: enterOrStart, }, { path: "/scan-contact", diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index dd4c412..2b34be2 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -383,11 +383,12 @@ export default class AccountViewView extends Vue { // 'created' hook runs when the Vue instance is first created async created() { - // Uncomment to register this user on the test server. + // Uncomment this to register this user on the test server. // To manage within the vue devtools browser extension https://devtools.vuejs.org/ // assign this to a class variable, eg. "registerThisUser = testServerRegisterUser", // select a component in the extension, and enter in the console: $vm.ctx.registerThisUser() //testServerRegisterUser(); + try { await db.open(); const settings = await db.settings.get(MASTER_SETTINGS_KEY); diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index ade22ae..11d2fdc 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -1,15 +1,231 @@ diff --git a/src/views/NewEditProjectView.vue b/src/views/NewEditProjectView.vue index 0644c9a..6277195 100644 --- a/src/views/NewEditProjectView.vue +++ b/src/views/NewEditProjectView.vue @@ -122,7 +122,7 @@ export default class NewEditProjectView extends Vue { await accountsDB.open(); const num_accounts = await accountsDB.accounts.count(); if (num_accounts === 0) { - console.error("Problem! Should have a profile!"); + console.error("Error: no account was found."); } else { const accounts = await accountsDB.accounts.toArray(); const account = R.find((acc) => acc.did === this.activeDid, accounts); @@ -222,7 +222,7 @@ export default class NewEditProjectView extends Vue { ); } } catch (error) { - let userMessage = "There was an error. See logs for more info."; + let userMessage = "There was an error saving the project."; const serverError = error as AxiosError; if (serverError) { this.isAlertVisible = true; @@ -254,7 +254,7 @@ export default class NewEditProjectView extends Vue { await accountsDB.open(); const num_accounts = await accountsDB.accounts.count(); if (num_accounts === 0) { - console.error("Problem! Should have a profile!"); + console.error("Error: there is no account."); } else { const accounts = await accountsDB.accounts.toArray(); const account = R.find((acc) => acc.did === this.activeDid, accounts); diff --git a/src/views/StatisticsView.vue b/src/views/StatisticsView.vue index 6aa730c..0276704 100644 --- a/src/views/StatisticsView.vue +++ b/src/views/StatisticsView.vue @@ -113,6 +113,7 @@ export default class StatisticsView extends Vue { world: World; worldProperties: WorldProperties = {}; + // 'mounted' hook runs after initial render mounted() { const container = document.querySelector("#scene-container"); const newWorld = new World(container, this);