mirror of
https://github.com/styppo/hamstr.git
synced 2024-10-18 13:33:22 +00:00
move LeftMenu to its own component, remove the notifications thing from before as it wasn't good enough, pre-step before saving events to ensure we don't save old metadata from people.
This commit is contained in:
parent
02e2fb8217
commit
c79859437e
@ -1,9 +1,11 @@
|
||||
import LeftMenu from '../components/LeftMenu.vue'
|
||||
import Publish from '../components/Publish.vue'
|
||||
import Balloon from '../components/Balloon.vue'
|
||||
import Reply from '../components/Reply.vue'
|
||||
import Post from '../components/Post.vue'
|
||||
|
||||
export default ({app}) => {
|
||||
app.component('LeftMenu', LeftMenu)
|
||||
app.component('Publish', Publish)
|
||||
app.component('Balloon', Balloon)
|
||||
app.component('Reply', Reply)
|
||||
|
118
src/components/LeftMenu.vue
Normal file
118
src/components/LeftMenu.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<q-dialog v-model="dialogPublish">
|
||||
<Publish />
|
||||
</q-dialog>
|
||||
|
||||
<div class="hidden sm:flex w-1/4 justify-center px-8">
|
||||
<q-card flat no-box-shadow class="text-xl">
|
||||
<q-card-section class="flex justify-center">
|
||||
<q-img src="/bird.png" fit="scale-down" width="80px" />
|
||||
</q-card-section>
|
||||
<q-list class="text-slate-700">
|
||||
<q-item v-ripple clickable :to="'/'" active-class="">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="home" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section
|
||||
:class="{
|
||||
'text-primary': $route.name === 'home'
|
||||
}"
|
||||
>
|
||||
Home
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-ripple clickable :to="'/notifications'" active-class="">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="notifications" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section
|
||||
:class="{'text-primary': $route.name === 'notifications'}"
|
||||
>
|
||||
Notifications
|
||||
|
||||
<q-badge
|
||||
v-if="notifications.length"
|
||||
color="primary"
|
||||
floating
|
||||
transparent
|
||||
>
|
||||
{{ notifications.length }}
|
||||
</q-badge>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-ripple clickable :to="'/messages'" active-class="">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="email" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section :class="{'text-primary': $route.name === 'messages'}">
|
||||
Messages
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item
|
||||
v-ripple
|
||||
clickable
|
||||
:to="'/' + $store.state.keys.pub"
|
||||
active-class=""
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="person" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section
|
||||
:class="{
|
||||
'text-primary':
|
||||
$route.name === 'profile' &&
|
||||
$route.params.pubkey === $store.state.keys.pub
|
||||
}"
|
||||
>
|
||||
Profile
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-ripple clickable :to="'/settings'" active-class="">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="settings" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section :class="{'text-primary': $route.name === 'settings'}">
|
||||
Settings
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<q-btn
|
||||
rounded
|
||||
unelevated
|
||||
color="primary"
|
||||
size="md"
|
||||
label="Publish"
|
||||
class="mx-2 my-4 py-2 px-4 w-full"
|
||||
@click="dialogPublish = true"
|
||||
></q-btn>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import helpersMixin from '../utils/mixin'
|
||||
|
||||
export default {
|
||||
name: 'LeftMenu',
|
||||
mixins: [helpersMixin],
|
||||
|
||||
data() {
|
||||
return {
|
||||
notifications: [],
|
||||
dialogPublish: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -35,7 +35,10 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-slate-500 cursor-pointer hover:underline text-xs">
|
||||
<div
|
||||
class="text-slate-500 cursor-pointer hover:underline text-xs"
|
||||
@click="toEvent(event.id)"
|
||||
>
|
||||
{{ niceDate(event.created_at) }}
|
||||
</div>
|
||||
</q-item-label>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<q-input v-model="text" dense label="Say something" maxlength="280">
|
||||
<template #before>
|
||||
<q-btn round class="mr-3" @click="toProfile($store.state.keys.pub)">
|
||||
<q-avatar rounded size="42px">
|
||||
<q-avatar round size="42px">
|
||||
<img :src="$store.getters.avatar($store.state.keys.pub)" />
|
||||
</q-avatar>
|
||||
</q-btn>
|
||||
|
40
src/db.js
40
src/db.js
@ -68,6 +68,39 @@ db.upsert('_design/main', current => {
|
||||
db.viewCleanup().then(r => console.log('view cleanup done', r))
|
||||
})
|
||||
|
||||
// general function for saving an event, with granular logic for each kind
|
||||
//
|
||||
export async function dbSave(event) {
|
||||
switch (event.kind) {
|
||||
case 0: {
|
||||
// first check if we don't have a newer metadata for this user
|
||||
let current = await dbGetProfile(event.pubkey)
|
||||
if (current.created_at >= event.created_at) {
|
||||
return
|
||||
}
|
||||
break
|
||||
}
|
||||
case 1:
|
||||
break
|
||||
case 2:
|
||||
break
|
||||
case 3:
|
||||
break
|
||||
case 4:
|
||||
break
|
||||
}
|
||||
|
||||
event._id = event.id
|
||||
|
||||
try {
|
||||
await db.put(event)
|
||||
} catch (err) {
|
||||
if (err.name !== 'conflict') {
|
||||
console.error('unexpected error saving event', event, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// db queries
|
||||
// ~
|
||||
export async function dbGetHomeFeedNotes(
|
||||
@ -202,12 +235,7 @@ export async function dbGetProfile(pubkey) {
|
||||
sorted
|
||||
.slice(1)
|
||||
.filter(row => row.doc)
|
||||
.forEach(row =>
|
||||
db
|
||||
.remove(row.doc)
|
||||
.then(x => console.log('deleted', x))
|
||||
.catch(e => console.log('failed to delete', e))
|
||||
)
|
||||
.forEach(row => db.remove(row.doc))
|
||||
return sorted[0].doc
|
||||
}
|
||||
}
|
||||
|
@ -1,110 +1,7 @@
|
||||
<template>
|
||||
<q-layout>
|
||||
<q-dialog v-model="dialogPublish">
|
||||
<Publish />
|
||||
</q-dialog>
|
||||
|
||||
<div class="flex">
|
||||
<div class="hidden sm:flex w-1/4 justify-center px-8">
|
||||
<q-card flat no-box-shadow class="text-xl">
|
||||
<q-card-section class="flex justify-center">
|
||||
<q-img src="/bird.png" fit="scale-down" width="80px" />
|
||||
</q-card-section>
|
||||
<q-list class="text-slate-700">
|
||||
<q-item v-ripple clickable :to="'/'" active-class="">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="home" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section
|
||||
:class="{
|
||||
'text-primary': $route.name === 'home'
|
||||
}"
|
||||
>
|
||||
Home
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-ripple clickable :to="'/notifications'" active-class="">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="notifications" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section
|
||||
:class="{'text-primary': $route.name === 'notifications'}"
|
||||
>
|
||||
Notifications
|
||||
|
||||
<q-badge
|
||||
v-if="Object.keys($store.state.notifications).length"
|
||||
color="primary"
|
||||
floating
|
||||
transparent
|
||||
>
|
||||
{{ Object.keys($store.state.notifications).length }}
|
||||
</q-badge>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-ripple clickable :to="'/messages'" active-class="">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="email" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section
|
||||
:class="{'text-primary': $route.name === 'messages'}"
|
||||
>
|
||||
Messages
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item
|
||||
v-ripple
|
||||
clickable
|
||||
:to="'/' + $store.state.keys.pub"
|
||||
active-class=""
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="person" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section
|
||||
:class="{
|
||||
'text-primary':
|
||||
$route.name === 'profile' &&
|
||||
$route.params.pubkey === $store.state.keys.pub
|
||||
}"
|
||||
>
|
||||
Profile
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-ripple clickable :to="'/settings'" active-class="">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="settings" color="secondary" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section
|
||||
:class="{'text-primary': $route.name === 'settings'}"
|
||||
>
|
||||
Settings
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<q-btn
|
||||
rounded
|
||||
unelevated
|
||||
color="primary"
|
||||
size="md"
|
||||
label="Publish"
|
||||
class="mx-2 my-4 py-2 px-4 w-full"
|
||||
@click="dialogPublish = true"
|
||||
></q-btn>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
<LeftMenu />
|
||||
|
||||
<div class="w-full sm:w-3/4 lg:w-2/4 pl-4">
|
||||
<q-page-container>
|
||||
@ -173,8 +70,6 @@ export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
dialogGenerate: false,
|
||||
dialogPublish: false,
|
||||
searchingProfile: ''
|
||||
}
|
||||
},
|
||||
|
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
|
||||
<div class="flex justify-left items-center mt-4">
|
||||
<q-avatar rounded>
|
||||
<q-avatar round>
|
||||
<img :src="$store.getters.avatar($route.params.pubkey)" />
|
||||
</q-avatar>
|
||||
<div class="ml-4">
|
||||
|
@ -2,7 +2,7 @@ import {encrypt, decrypt} from 'nostr-tools/nip04'
|
||||
import {Notify} from 'quasar'
|
||||
|
||||
import {pool} from '../pool'
|
||||
import {db, dbGetProfile} from '../db'
|
||||
import {dbSave, dbGetProfile} from '../db'
|
||||
|
||||
export function launch(store) {
|
||||
if (!store.state.keys.pub) {
|
||||
@ -177,24 +177,15 @@ export async function sendChatMessage(store, {pubkey, text, replyTo}) {
|
||||
}
|
||||
|
||||
export async function addEvent(store, event) {
|
||||
event._id = event.id
|
||||
|
||||
db.put(event).catch(err => {
|
||||
if (err.name === 'conflict') return
|
||||
console.error(err)
|
||||
})
|
||||
await dbSave(event)
|
||||
|
||||
// do things after the event is saved
|
||||
switch (event.kind) {
|
||||
case 0:
|
||||
// this will reset the profile cache for this URL
|
||||
store.dispatch('useProfile', event.pubkey)
|
||||
break
|
||||
case 1:
|
||||
if (
|
||||
event.tags.find(([t, v]) => t === 'p' && v === store.state.keys.pub)
|
||||
) {
|
||||
store.dispatch('addNotification', event)
|
||||
}
|
||||
break
|
||||
case 2:
|
||||
break
|
||||
|
@ -92,7 +92,3 @@ export function addProfileToCache(state, event) {
|
||||
state.me = JSON.parse(event.content)
|
||||
}
|
||||
}
|
||||
|
||||
export function addNotification(state, event) {
|
||||
state.notifications[event.id] = true
|
||||
}
|
||||
|
@ -8,8 +8,6 @@ export default function () {
|
||||
following: LocalStorage.getItem('following') || [], // [ pubkeys... ]
|
||||
|
||||
profilesCache: {}, // { [pubkey]: {name, about, picture, ...} }
|
||||
profilesCacheLRU: [], // [ pubkeys... ]
|
||||
|
||||
notifications: {}
|
||||
profilesCacheLRU: [] // [ pubkeys... ]
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user