start work on favoriting
This commit is contained in:
parent
ae04fddd68
commit
3a17f7ff7b
22
routes/_actions/favorite.js
Normal file
22
routes/_actions/favorite.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { favoriteStatus, unfavoriteStatus } from '../_api/favorite'
|
||||||
|
import { store } from '../_store/store'
|
||||||
|
import { database } from '../_database/database'
|
||||||
|
import { toast } from '../_utils/toast'
|
||||||
|
|
||||||
|
export async function setFavorited(statusId, favorited) {
|
||||||
|
let instanceName = store.get('currentInstance')
|
||||||
|
let accessToken = store.get('accessToken')
|
||||||
|
try {
|
||||||
|
let status = await (favorited
|
||||||
|
? favoriteStatus(instanceName, accessToken, statusId)
|
||||||
|
: unfavoriteStatus(instanceName, accessToken, statusId))
|
||||||
|
await database.insertStatus(instanceName, status)
|
||||||
|
let statusModifications = store.get('statusModifications')
|
||||||
|
let currentStatusModifications = statusModifications[instanceName] =
|
||||||
|
(statusModifications[instanceName] || {favorites: {}, reblogs: {}})
|
||||||
|
currentStatusModifications.favorites[statusId] = favorited
|
||||||
|
store.set({statusModifications: statusModifications})
|
||||||
|
} catch (e) {
|
||||||
|
toast.say('Failed to favorite/unfavorite. Please try again.')
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
import { get, paramsString } from '../_utils/ajax'
|
import { getWithTimeout, paramsString } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
export async function getBlockedAccounts (instanceName, accessToken, limit = 80) {
|
export async function getBlockedAccounts (instanceName, accessToken, limit = 80) {
|
||||||
let url = `${basename(instanceName)}/api/v1/blocks`
|
let url = `${basename(instanceName)}/api/v1/blocks`
|
||||||
url += '?' + paramsString({ limit })
|
url += '?' + paramsString({ limit })
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export async function getBlockedAccounts (instanceName, accessToken, limit = 80)
|
||||||
export async function getMutedAccounts (instanceName, accessToken, limit = 80) {
|
export async function getMutedAccounts (instanceName, accessToken, limit = 80) {
|
||||||
let url = `${basename(instanceName)}/api/v1/mutes`
|
let url = `${basename(instanceName)}/api/v1/mutes`
|
||||||
url += '?' + paramsString({ limit })
|
url += '?' + paramsString({ limit })
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
16
routes/_api/favorite.js
Normal file
16
routes/_api/favorite.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { post } from '../_utils/ajax'
|
||||||
|
import { basename } from './utils'
|
||||||
|
|
||||||
|
export async function favoriteStatus(instanceName, accessToken, statusId) {
|
||||||
|
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/favourite`
|
||||||
|
return post(url, null, {
|
||||||
|
'Authorization': `Bearer ${accessToken}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function unfavoriteStatus(instanceName, accessToken, statusId) {
|
||||||
|
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unfavourite`
|
||||||
|
return post(url, null, {
|
||||||
|
'Authorization': `Bearer ${accessToken}`
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { get } from '../_utils/ajax'
|
import { getWithTimeout } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
export function getInstanceInfo (instanceName) {
|
export function getInstanceInfo (instanceName) {
|
||||||
let url = `${basename(instanceName)}/api/v1/instance`
|
let url = `${basename(instanceName)}/api/v1/instance`
|
||||||
return get(url)
|
return getWithTimeout(url)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { get } from '../_utils/ajax'
|
import { getWithTimeout } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
export function getLists (instanceName, accessToken) {
|
export function getLists (instanceName, accessToken) {
|
||||||
let url = `${basename(instanceName)}/api/v1/lists`
|
let url = `${basename(instanceName)}/api/v1/lists`
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { post, paramsString } from '../_utils/ajax'
|
import { postWithTimeout, paramsString } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
const WEBSITE = 'https://pinafore.social'
|
const WEBSITE = 'https://pinafore.social'
|
||||||
|
@ -7,7 +7,7 @@ const CLIENT_NAME = 'Pinafore'
|
||||||
|
|
||||||
export function registerApplication (instanceName, redirectUri) {
|
export function registerApplication (instanceName, redirectUri) {
|
||||||
const url = `${basename(instanceName)}/api/v1/apps`
|
const url = `${basename(instanceName)}/api/v1/apps`
|
||||||
return post(url, {
|
return postWithTimeout(url, {
|
||||||
client_name: CLIENT_NAME,
|
client_name: CLIENT_NAME,
|
||||||
redirect_uris: redirectUri,
|
redirect_uris: redirectUri,
|
||||||
scopes: SCOPES,
|
scopes: SCOPES,
|
||||||
|
@ -27,7 +27,7 @@ export function generateAuthLink (instanceName, clientId, redirectUri) {
|
||||||
|
|
||||||
export function getAccessTokenFromAuthCode (instanceName, clientId, clientSecret, code, redirectUri) {
|
export function getAccessTokenFromAuthCode (instanceName, clientId, clientSecret, code, redirectUri) {
|
||||||
let url = `${basename(instanceName)}/oauth/token`
|
let url = `${basename(instanceName)}/oauth/token`
|
||||||
return post(url, {
|
return postWithTimeout(url, {
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
client_secret: clientSecret,
|
client_secret: clientSecret,
|
||||||
redirect_uri: redirectUri,
|
redirect_uri: redirectUri,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { get, paramsString } from '../_utils/ajax'
|
import { getWithTimeout, paramsString } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
export async function getPinnedStatuses (instanceName, accessToken, accountId) {
|
export async function getPinnedStatuses (instanceName, accessToken, accountId) {
|
||||||
|
@ -7,7 +7,7 @@ export async function getPinnedStatuses (instanceName, accessToken, accountId) {
|
||||||
limit: 40,
|
limit: 40,
|
||||||
pinned: true
|
pinned: true
|
||||||
})
|
})
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { get, paramsString } from '../_utils/ajax'
|
import { getWithTimeout, paramsString } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
export async function getReblogs (instanceName, accessToken, statusId, limit = 80) {
|
export async function getReblogs (instanceName, accessToken, statusId, limit = 80) {
|
||||||
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/reblogged_by`
|
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/reblogged_by`
|
||||||
url += '?' + paramsString({ limit })
|
url += '?' + paramsString({ limit })
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export async function getReblogs (instanceName, accessToken, statusId, limit = 8
|
||||||
export async function getFavorites (instanceName, accessToken, statusId, limit = 80) {
|
export async function getFavorites (instanceName, accessToken, statusId, limit = 80) {
|
||||||
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/favourited_by`
|
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/favourited_by`
|
||||||
url += '?' + paramsString({ limit })
|
url += '?' + paramsString({ limit })
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { get, paramsString } from '../_utils/ajax'
|
import { getWithTimeout, paramsString } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
export function search (instanceName, accessToken, query) {
|
export function search (instanceName, accessToken, query) {
|
||||||
|
@ -6,7 +6,7 @@ export function search (instanceName, accessToken, query) {
|
||||||
q: query,
|
q: query,
|
||||||
resolve: true
|
resolve: true
|
||||||
})
|
})
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { get, paramsString } from '../_utils/ajax'
|
import { getWithTimeout, paramsString } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
function getTimelineUrlPath (timeline) {
|
function getTimelineUrlPath (timeline) {
|
||||||
|
@ -57,14 +57,14 @@ export function getTimeline (instanceName, accessToken, timeline, maxId, since)
|
||||||
// special case - this is a list of descendents and ancestors
|
// special case - this is a list of descendents and ancestors
|
||||||
let statusUrl = `${basename(instanceName)}/api/v1/statuses/${timeline.split('/').slice(-1)[0]}}`
|
let statusUrl = `${basename(instanceName)}/api/v1/statuses/${timeline.split('/').slice(-1)[0]}}`
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
get(url, {'Authorization': `Bearer ${accessToken}`}),
|
getWithTimeout(url, {'Authorization': `Bearer ${accessToken}`}),
|
||||||
get(statusUrl, {'Authorization': `Bearer ${accessToken}`})
|
getWithTimeout(statusUrl, {'Authorization': `Bearer ${accessToken}`})
|
||||||
]).then(res => {
|
]).then(res => {
|
||||||
return [].concat(res[0].ancestors).concat([res[1]]).concat(res[0].descendants)
|
return [].concat(res[0].ancestors).concat([res[1]]).concat(res[0].descendants)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { get, paramsString } from '../_utils/ajax'
|
import { getWithTimeout, paramsString } from '../_utils/ajax'
|
||||||
import { basename } from './utils'
|
import { basename } from './utils'
|
||||||
|
|
||||||
export function getVerifyCredentials (instanceName, accessToken) {
|
export function getVerifyCredentials (instanceName, accessToken) {
|
||||||
let url = `${basename(instanceName)}/api/v1/accounts/verify_credentials`
|
let url = `${basename(instanceName)}/api/v1/accounts/verify_credentials`
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAccount (instanceName, accessToken, accountId) {
|
export function getAccount (instanceName, accessToken, accountId) {
|
||||||
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}`
|
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}`
|
||||||
return get(url, {
|
return getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ export function getAccount (instanceName, accessToken, accountId) {
|
||||||
export async function getRelationship (instanceName, accessToken, accountId) {
|
export async function getRelationship (instanceName, accessToken, accountId) {
|
||||||
let url = `${basename(instanceName)}/api/v1/accounts/relationships`
|
let url = `${basename(instanceName)}/api/v1/accounts/relationships`
|
||||||
url += '?' + paramsString({id: accountId})
|
url += '?' + paramsString({id: accountId})
|
||||||
let res = await get(url, {
|
let res = await getWithTimeout(url, {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
return res[0]
|
return res[0]
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<IconButton
|
<IconButton
|
||||||
label="Favorite"
|
label="Favorite"
|
||||||
pressable="true"
|
pressable="true"
|
||||||
pressed="{{status.favourited}}"
|
pressed="{{favorited}}"
|
||||||
href="#fa-star"
|
href="#fa-star"
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
@ -32,13 +32,14 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import IconButton from '../IconButton.html'
|
import IconButton from '../IconButton.html'
|
||||||
|
import { store } from '../../_store/store'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
IconButton
|
IconButton
|
||||||
},
|
},
|
||||||
|
store: () => store,
|
||||||
computed: {
|
computed: {
|
||||||
visibility: (status) => status.visibility,
|
visibility: (status) => status.visibility,
|
||||||
boostLabel: (visibility) => {
|
boostLabel: (visibility) => {
|
||||||
|
@ -63,6 +64,12 @@
|
||||||
},
|
},
|
||||||
boostDisabled: (visibility) => {
|
boostDisabled: (visibility) => {
|
||||||
return visibility === 'private' || visibility === 'direct'
|
return visibility === 'private' || visibility === 'direct'
|
||||||
|
},
|
||||||
|
favorited: (status, $currentStatusModifications) => {
|
||||||
|
if ($currentStatusModifications && status.id in $currentStatusModifications.favorites) {
|
||||||
|
return $currentStatusModifications.favorites[status.id]
|
||||||
|
}
|
||||||
|
return status.favourited
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,3 +388,15 @@ export async function getNotificationIdsForStatus (instanceName, statusId) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// insert statuses
|
||||||
|
//
|
||||||
|
|
||||||
|
export async function insertStatus(instanceName, status) {
|
||||||
|
const db = await getDatabase(instanceName)
|
||||||
|
cacheStatus(statusesCache, status)
|
||||||
|
return dbPromise(db, STATUSES_STORE, 'readwrite', (statusesStore) => {
|
||||||
|
putStatus(statusesStore, status)
|
||||||
|
})
|
||||||
|
}
|
|
@ -95,4 +95,10 @@ export function instanceComputations (store) {
|
||||||
return !!numberOfNotifications
|
return !!numberOfNotifications
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
store.compute('currentStatusModifications',
|
||||||
|
['statusModifications', 'instanceName'],
|
||||||
|
(statusModifications, instanceName) => {
|
||||||
|
return statusModifications[instanceName]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@ export const store = new PinaforeStore({
|
||||||
pinnedPages: {},
|
pinnedPages: {},
|
||||||
instanceLists: {},
|
instanceLists: {},
|
||||||
pinnedStatuses: {},
|
pinnedStatuses: {},
|
||||||
instanceInfos: {}
|
instanceInfos: {},
|
||||||
|
statusModifications: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
mixins(PinaforeStore)
|
mixins(PinaforeStore)
|
||||||
|
|
|
@ -1,25 +1,50 @@
|
||||||
const TIMEOUT = 15000
|
const TIMEOUT = 15000
|
||||||
|
|
||||||
function fetchWithTimeout (url, options) {
|
function fetchWithTimeout (url, options) {
|
||||||
return Promise.race([
|
return new Promise((resolve, reject) => {
|
||||||
fetch(url, options),
|
fetch(url, options).then(resolve, reject)
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
setTimeout(() => reject(new Error(`Timed out after ${TIMEOUT / 1000} seconds`)), TIMEOUT)
|
setTimeout(() => reject(new Error(`Timed out after ${TIMEOUT / 1000} seconds`)), TIMEOUT)
|
||||||
})
|
})
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function post (url, body) {
|
async function _post (url, body, headers, timeout) {
|
||||||
return (await fetchWithTimeout(url, {
|
let fetchFunc = timeout ? fetchWithTimeout : fetch
|
||||||
|
return (await fetchFunc(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: Object.assign(headers, {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
}),
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
})).json()
|
})).json()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function _get (url, headers, timeout) {
|
||||||
|
let fetchFunc = timeout ? fetchWithTimeout : fetch
|
||||||
|
return (await fetchFunc(url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: Object.assign(headers, {
|
||||||
|
'Accept': 'application/json'
|
||||||
|
})
|
||||||
|
})).json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function post (url, body, headers = {}) {
|
||||||
|
return _post(url, body, headers, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function postWithTimeout (url, body, headers = {}) {
|
||||||
|
return _post(url, body, headers, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getWithTimeout (url, headers = {}) {
|
||||||
|
return _get(url, headers, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function get (url, headers = {}) {
|
||||||
|
return _get(url, headers, false)
|
||||||
|
}
|
||||||
|
|
||||||
export function paramsString (paramsObject) {
|
export function paramsString (paramsObject) {
|
||||||
let params = new URLSearchParams()
|
let params = new URLSearchParams()
|
||||||
Object.keys(paramsObject).forEach(key => {
|
Object.keys(paramsObject).forEach(key => {
|
||||||
|
@ -27,12 +52,3 @@ export function paramsString (paramsObject) {
|
||||||
})
|
})
|
||||||
return params.toString()
|
return params.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get (url, headers = {}) {
|
|
||||||
return (await fetchWithTimeout(url, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: Object.assign(headers, {
|
|
||||||
'Accept': 'application/json'
|
|
||||||
})
|
|
||||||
})).json()
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue