diff --git a/routes/_actions/instances.js b/routes/_actions/instances.js
index 86f8e63..5ad962c 100644
--- a/routes/_actions/instances.js
+++ b/routes/_actions/instances.js
@@ -38,7 +38,9 @@ export async function logOutOfInstance (instanceName) {
loggedInInstances: loggedInInstances,
instanceThemes: instanceThemes,
loggedInInstancesInOrder: loggedInInstancesInOrder,
- currentInstance: newInstance
+ currentInstance: newInstance,
+ searchResults: null,
+ queryInSearch: ''
})
store.save()
toast.say(`Logged out of ${instanceName}`)
diff --git a/routes/_actions/pinnedStatuses.js b/routes/_actions/pinnedStatuses.js
new file mode 100644
index 0000000..4956c0e
--- /dev/null
+++ b/routes/_actions/pinnedStatuses.js
@@ -0,0 +1,23 @@
+import { store } from '../_store/store'
+import { cacheFirstUpdateAfter } from '../_utils/sync'
+import { getPinnedStatuses } from '../_api/pinnedStatuses'
+import { database } from '../_database/database'
+
+export async function updatePinnedStatusesForAccount(accountId) {
+ let instanceName = store.get('currentInstance')
+ let accessToken = store.get('accessToken')
+
+ await cacheFirstUpdateAfter(
+ () => getPinnedStatuses(instanceName, accessToken, accountId),
+ () => database.getPinnedStatuses(instanceName, accountId),
+ statuses => database.insertPinnedStatuses(instanceName, accountId, statuses),
+ statuses => {
+ let $pinnedStatuses = store.get('pinnedStatuses')
+ $pinnedStatuses[instanceName] = $pinnedStatuses[instanceName] || {}
+ $pinnedStatuses[instanceName][accountId] = statuses
+ store.set({pinnedStatuses: $pinnedStatuses})
+ }
+ )
+
+
+}
\ No newline at end of file
diff --git a/routes/_components/search/Search.html b/routes/_components/search/Search.html
index e1c3c82..48d6330 100644
--- a/routes/_components/search/Search.html
+++ b/routes/_components/search/Search.html
@@ -77,10 +77,13 @@
this.set({loading: true})
try {
let results = await search(instanceName, accessToken, queryInSearch)
- this.store.set({
- searchResultsForQuery: queryInSearch,
- searchResults: results
- })
+ let currentQueryInSearch = this.store.get('queryInSearch') // avoid race conditions
+ if (currentQueryInSearch === queryInSearch) {
+ this.store.set({
+ searchResultsForQuery: queryInSearch,
+ searchResults: results
+ })
+ }
} catch (e) {
toast.say('Error during search: ' + (e.name || '') + ' ' + (e.message || ''))
console.error(e)
diff --git a/routes/_components/status/Status.html b/routes/_components/status/Status.html
index 02601cf..233bc26 100644
--- a/routes/_components/status/Status.html
+++ b/routes/_components/status/Status.html
@@ -7,8 +7,8 @@
aria-setsize="{{length}}"
aria-label="Status by {{originalStatus.account.display_name || originalStatus.account.username}}"
on:recalculateHeight>
- {{#if (notification && (notification.type === 'reblog' || notification.type === 'favourite')) || status.reblog}}
-
+ {{#if (notification && (notification.type === 'reblog' || notification.type === 'favourite')) || status.reblog || timelineType === 'pinned'}}
+
{{/if}}
diff --git a/routes/_components/status/StatusHeader.html b/routes/_components/status/StatusHeader.html
index 8836d6d..791a151 100644
--- a/routes/_components/status/StatusHeader.html
+++ b/routes/_components/status/StatusHeader.html
@@ -1,21 +1,24 @@
@@ -66,18 +69,18 @@
export default {
computed: {
statusId: (status) => status.id,
- focusKey: (statusId) => `status-header-${statusId}`
- },
- helpers: {
- getIcon(notification, status) {
- if ((notification && notification.type === 'reblog') || (status && status.reblog)) {
+ focusKey: (statusId) => `status-header-${statusId}`,
+ icon: (notification, status, timelineType) => {
+ if (timelineType === 'pinned') {
+ return '#fa-thumb-tack'
+ } else if ((notification && notification.type === 'reblog') || (status && status.reblog)) {
return '#fa-retweet'
} else if (notification && notification.type === 'follow') {
return '#fa-user-plus'
}
return '#fa-star'
},
- getAccount(notification, status) {
+ account: (notification, status) => {
if (notification && notification.account) {
return notification.account
}
diff --git a/routes/_components/timeline/PinnedStatuses.html b/routes/_components/timeline/PinnedStatuses.html
new file mode 100644
index 0000000..1fa7d4d
--- /dev/null
+++ b/routes/_components/timeline/PinnedStatuses.html
@@ -0,0 +1,35 @@
+
+ {{#if pinnedStatuses}}
+ {{#each pinnedStatuses as status, index}}
+
+ {{/each}}
+ {{/if}}
+
+
\ No newline at end of file
diff --git a/routes/_database/constants.js b/routes/_database/constants.js
index 03454d8..e69def9 100644
--- a/routes/_database/constants.js
+++ b/routes/_database/constants.js
@@ -5,3 +5,4 @@ export const ACCOUNTS_STORE = 'accounts'
export const RELATIONSHIPS_STORE = 'relationships'
export const NOTIFICATIONS_STORE = 'notifications'
export const NOTIFICATION_TIMELINES_STORE = 'notification_timelines'
+export const PINNED_STATUSES_STORE = 'pinned_statuses'
diff --git a/routes/_database/databaseLifecycle.js b/routes/_database/databaseLifecycle.js
index d40e618..78ff571 100644
--- a/routes/_database/databaseLifecycle.js
+++ b/routes/_database/databaseLifecycle.js
@@ -5,13 +5,14 @@ import {
ACCOUNTS_STORE,
RELATIONSHIPS_STORE,
NOTIFICATIONS_STORE,
- NOTIFICATION_TIMELINES_STORE
+ NOTIFICATION_TIMELINES_STORE,
+ PINNED_STATUSES_STORE
} from './constants'
const openReqs = {}
const databaseCache = {}
-const DB_VERSION = 1
+const DB_VERSION = 2
export function getDatabase (instanceName) {
if (!instanceName) {
@@ -30,15 +31,20 @@ export function getDatabase (instanceName) {
}
req.onupgradeneeded = (e) => {
let db = req.result
- db.createObjectStore(META_STORE, {keyPath: 'key'})
- db.createObjectStore(STATUSES_STORE, {keyPath: 'id'})
- db.createObjectStore(ACCOUNTS_STORE, {keyPath: 'id'})
- db.createObjectStore(RELATIONSHIPS_STORE, {keyPath: 'id'})
- db.createObjectStore(NOTIFICATIONS_STORE, {keyPath: 'id'})
- db.createObjectStore(STATUS_TIMELINES_STORE, {keyPath: 'id'})
+ if (e.oldVersion < 1) {
+ db.createObjectStore(META_STORE, {keyPath: 'key'})
+ db.createObjectStore(STATUSES_STORE, {keyPath: 'id'})
+ db.createObjectStore(ACCOUNTS_STORE, {keyPath: 'id'})
+ db.createObjectStore(RELATIONSHIPS_STORE, {keyPath: 'id'})
+ db.createObjectStore(NOTIFICATIONS_STORE, {keyPath: 'id'})
+ db.createObjectStore(STATUS_TIMELINES_STORE, {keyPath: 'id'})
.createIndex('statusId', 'statusId')
- db.createObjectStore(NOTIFICATION_TIMELINES_STORE, {keyPath: 'id'})
+ db.createObjectStore(NOTIFICATION_TIMELINES_STORE, {keyPath: 'id'})
.createIndex('notificationId', 'notificationId')
+ }
+ if (e.oldVersion < 2) {
+ db.createObjectStore(PINNED_STATUSES_STORE, {keyPath: 'id'})
+ }
}
req.onsuccess = () => resolve(req.result)
})
diff --git a/routes/_database/timelines.js b/routes/_database/timelines.js
index 0a18a15..ac2eca4 100644
--- a/routes/_database/timelines.js
+++ b/routes/_database/timelines.js
@@ -1,10 +1,10 @@
-import { toReversePaddedBigInt } from './utils'
+import { toPaddedBigInt, toReversePaddedBigInt } from './utils'
import { dbPromise, getDatabase } from './databaseLifecycle'
import { accountsCache, getInCache, hasInCache, notificationsCache, setInCache, statusesCache } from './cache'
import {
ACCOUNTS_STORE,
NOTIFICATION_TIMELINES_STORE,
- NOTIFICATIONS_STORE,
+ NOTIFICATIONS_STORE, PINNED_STATUSES_STORE,
STATUS_TIMELINES_STORE,
STATUSES_STORE
} from './constants'
@@ -57,6 +57,14 @@ function cloneForStorage (obj) {
return res
}
+function cacheStatus(status, instanceName) {
+ setInCache(statusesCache, instanceName, status.id, status)
+ setInCache(accountsCache, instanceName, status.account.id, status.account)
+ if (status.reblog) {
+ setInCache(accountsCache, instanceName, status.reblog.account.id, status.reblog.account)
+ }
+}
+
//
// pagination
//
@@ -214,11 +222,7 @@ async function insertTimelineNotifications (instanceName, timeline, notification
async function insertTimelineStatuses (instanceName, timeline, statuses) {
for (let status of statuses) {
- setInCache(statusesCache, instanceName, status.id, status)
- setInCache(accountsCache, instanceName, status.account.id, status.account)
- if (status.reblog) {
- setInCache(accountsCache, instanceName, status.reblog.account.id, status.reblog.account)
- }
+ cacheStatus(status, instanceName)
}
const db = await getDatabase(instanceName)
let storeNames = [STATUS_TIMELINES_STORE, STATUSES_STORE, ACCOUNTS_STORE]
@@ -271,3 +275,47 @@ export async function getNotification (instanceName, id) {
setInCache(notificationsCache, instanceName, id, result)
return result
}
+
+//
+// pinned statuses
+//
+
+export async function insertPinnedStatuses (instanceName, accountId, statuses) {
+ for (let status of statuses) {
+ cacheStatus(status, instanceName)
+ }
+ const db = await getDatabase(instanceName)
+ let storeNames = [PINNED_STATUSES_STORE, STATUSES_STORE, ACCOUNTS_STORE]
+ await dbPromise(db, storeNames, 'readwrite', (stores) => {
+ let [ pinnedStatusesStore, statusesStore, accountsStore ] = stores
+ statuses.forEach((status, i) => {
+ storeStatus(statusesStore, accountsStore, status)
+ pinnedStatusesStore.put({
+ id: accountId + '\u0000' + toPaddedBigInt(i),
+ statusId: status.id
+ })
+ })
+ })
+}
+
+export async function getPinnedStatuses (instanceName, accountId) {
+ let storeNames = [PINNED_STATUSES_STORE, STATUSES_STORE, ACCOUNTS_STORE]
+ const db = await getDatabase(instanceName)
+ return dbPromise(db, storeNames, 'readonly', (stores, callback) => {
+ let [ pinnedStatusesStore, statusesStore, accountsStore ] = stores
+ let keyRange = IDBKeyRange.bound(
+ accountId + '\u0000',
+ accountId + '\u0000\uffff'
+ )
+ pinnedStatusesStore.getAll(keyRange).onsuccess = e => {
+ let pinnedResults = e.target.result
+ let res = new Array(pinnedResults.length)
+ pinnedResults.forEach((pinnedResult, i) => {
+ fetchStatus(statusesStore, accountsStore, pinnedResult.statusId, status => {
+ res[i] = status
+ })
+ })
+ callback(res)
+ }
+ })
+}
\ No newline at end of file
diff --git a/routes/_store/store.js b/routes/_store/store.js
index ab37262..70071d0 100644
--- a/routes/_store/store.js
+++ b/routes/_store/store.js
@@ -34,7 +34,8 @@ const store = new PinaforeStore({
autoplayGifs: false,
markMediaAsSensitive: false,
pinnedPages: {},
- instanceLists: {}
+ instanceLists: {},
+ pinnedStatuses: {}
})
mixins(PinaforeStore)
diff --git a/routes/accounts/[accountId].html b/routes/accounts/[accountId].html
index d9638d2..64107ed 100644
--- a/routes/accounts/[accountId].html
+++ b/routes/accounts/[accountId].html
@@ -13,6 +13,7 @@
verifyCredentials="{{$currentVerifyCredentials}}"
/>
{{/if}}
+
{{else}}
@@ -34,6 +35,7 @@
import { updateProfileAndRelationship } from '../_actions/accounts'
import AccountProfile from '../_components/AccountProfile.html'
import { updateVerifyCredentialsForInstance } from '../_actions/instances'
+ import PinnedStatuses from '../_components/timeline/PinnedStatuses.html'
export default {
oncreate() {
@@ -57,7 +59,8 @@
FreeTextLayout,
HiddenFromSSR,
DynamicPageBanner,
- AccountProfile
+ AccountProfile,
+ PinnedStatuses
}
}
\ No newline at end of file