parent
df6b75e994
commit
58d1f62b2b
11
src/routes/_actions/showShareDialogIfNecessary.js
Normal file
11
src/routes/_actions/showShareDialogIfNecessary.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { store } from '../_store/store'
|
||||
import { importShowComposeDialog } from '../_components/dialog/asyncDialogs'
|
||||
|
||||
export async function showShareDialogIfNecessary () {
|
||||
let { isUserLoggedIn, openShareDialog } = store.get()
|
||||
store.set({ openShareDialog: false })
|
||||
if (isUserLoggedIn && openShareDialog) {
|
||||
let showComposeDialog = await importShowComposeDialog()
|
||||
showComposeDialog()
|
||||
}
|
||||
}
|
|
@ -7,9 +7,28 @@
|
|||
import NotLoggedInHome from '../_components/NotLoggedInHome.html'
|
||||
import { store } from '../_store/store.js'
|
||||
import TimelineHomePage from '../_components/TimelineHomePage.html'
|
||||
import { observe } from 'svelte-extras'
|
||||
import { showShareDialogIfNecessary } from '../_actions/showShareDialogIfNecessary'
|
||||
|
||||
export default {
|
||||
async oncreate () {
|
||||
let observed = false
|
||||
this.observe('currentVerifyCredentials', verifyCredentials => {
|
||||
if (verifyCredentials && !observed) {
|
||||
// when the verifyCredentials object is available, we can check to see
|
||||
// if the user is trying to share something, then share it
|
||||
observed = true
|
||||
/* no await */ showShareDialogIfNecessary()
|
||||
}
|
||||
})
|
||||
},
|
||||
store: () => store,
|
||||
computed: {
|
||||
currentVerifyCredentials: ({ $currentVerifyCredentials }) => $currentVerifyCredentials
|
||||
},
|
||||
methods: {
|
||||
observe
|
||||
},
|
||||
components: {
|
||||
NotLoggedInHome,
|
||||
TimelineHomePage
|
||||
|
|
|
@ -44,13 +44,15 @@ async function doRefreshInstanceDataAndStream (store, instanceName) {
|
|||
|
||||
async function refreshInstanceData (instanceName) {
|
||||
// these are all low-priority
|
||||
scheduleIdleTask(() => updateVerifyCredentialsForInstance(instanceName))
|
||||
scheduleIdleTask(() => updateCustomEmojiForInstance(instanceName))
|
||||
scheduleIdleTask(() => updateListsForInstance(instanceName))
|
||||
scheduleIdleTask(() => updatePushSubscriptionForInstance(instanceName))
|
||||
|
||||
// this is the only critical one
|
||||
await updateInstanceInfo(instanceName)
|
||||
// these are the only critical ones
|
||||
await Promise.all([
|
||||
updateInstanceInfo(instanceName),
|
||||
updateVerifyCredentialsForInstance(instanceName)
|
||||
])
|
||||
}
|
||||
|
||||
function stream (store, instanceName, currentInstanceInfo) {
|
||||
|
|
|
@ -46,7 +46,8 @@ const nonPersistedState = {
|
|||
sensitivesShown: {},
|
||||
spoilersShown: {},
|
||||
statusModifications: {},
|
||||
verifyCredentials: {}
|
||||
verifyCredentials: {},
|
||||
openShareDialog: false
|
||||
}
|
||||
|
||||
const state = Object.assign({}, persistedState, nonPersistedState)
|
||||
|
|
7
src/routes/_utils/decodeURIComponentWithPluses.js
Normal file
7
src/routes/_utils/decodeURIComponentWithPluses.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Per the web share target spec: https://wicg.github.io/web-share-target/
|
||||
// U+0020 (SPACE) characters are encoded as "+", due to the use of
|
||||
// application/x-www-form-urlencoded encoding, not "%20" as might be expected.
|
||||
|
||||
export function decodeURIComponentWithPluses (text) {
|
||||
return text.split('+').map(decodeURIComponent).join(' ')
|
||||
}
|
27
src/routes/share.html
Normal file
27
src/routes/share.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<!-- this is just used for the web share target API -->
|
||||
<script>
|
||||
import { store } from './_store/store'
|
||||
import { goto } from '../../__sapper__/client'
|
||||
import { decodeURIComponentWithPluses } from './_utils/decodeURIComponentWithPluses'
|
||||
|
||||
const SHARE_KEYS = ['title', 'text', 'url']
|
||||
|
||||
export default {
|
||||
store: () => store,
|
||||
oncreate () {
|
||||
let params = new URLSearchParams(location.search)
|
||||
|
||||
let text = SHARE_KEYS
|
||||
.map(key => params.get(key) && decodeURIComponentWithPluses(params.get(key)))
|
||||
.filter(Boolean)
|
||||
.join(' ')
|
||||
|
||||
this.store.set({ openShareDialog: true })
|
||||
this.store.clearComposeData('dialog')
|
||||
this.store.setComposeData('dialog', { text })
|
||||
this.store.save()
|
||||
|
||||
goto('/', { replaceState: true })
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -6,6 +6,17 @@
|
|||
"description": "Alternative web client for Mastodon, focused on speed and simplicity.",
|
||||
"display": "standalone",
|
||||
"start_url": "/?pwa=true",
|
||||
"share_target": {
|
||||
"action": "/share",
|
||||
"method": "GET",
|
||||
"enctype": "application/x-www-form-urlencoded",
|
||||
"url_template": "/share?title={title}&text={text}&url={url}",
|
||||
"params": {
|
||||
"title": "title",
|
||||
"text": "text",
|
||||
"url": "url"
|
||||
}
|
||||
},
|
||||
"icons": [
|
||||
{
|
||||
"src": "icon-48.png",
|
||||
|
|
58
tests/spec/027-share-target.js
Normal file
58
tests/spec/027-share-target.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
import {
|
||||
closeDialogButton,
|
||||
composeModalInput,
|
||||
getUrl, goBack, modalDialog, notificationsNavButton
|
||||
} from '../utils'
|
||||
import { loginAsFoobar } from '../roles'
|
||||
|
||||
fixture`027-share-target.js`
|
||||
.page`http://localhost:4002`
|
||||
|
||||
const SHARE_URL = 'http://localhost:4002/share?' +
|
||||
'title=My+cool+title&' +
|
||||
'text=This+is+a+bit+clich%C3%A9&' +
|
||||
'url=http%3A%2F%2Fexample.com'
|
||||
|
||||
const SHARE_TEXT = 'My cool title This is a bit cliché http://example.com'
|
||||
|
||||
test('Share target works when page is not open', async t => {
|
||||
await loginAsFoobar(t)
|
||||
await t
|
||||
.navigateTo('about:blank')
|
||||
.navigateTo(SHARE_URL)
|
||||
.expect(getUrl()).eql('http://localhost:4002/')
|
||||
.expect(modalDialog.hasAttribute('aria-hidden')).notOk()
|
||||
.expect(composeModalInput.value).eql(SHARE_TEXT)
|
||||
})
|
||||
|
||||
test('Share target works when page is open', async t => {
|
||||
await loginAsFoobar(t)
|
||||
await t
|
||||
.navigateTo(SHARE_URL)
|
||||
.expect(getUrl()).eql('http://localhost:4002/')
|
||||
.expect(modalDialog.hasAttribute('aria-hidden')).notOk()
|
||||
.expect(composeModalInput.value).eql(SHARE_TEXT)
|
||||
})
|
||||
|
||||
test('Share target page replaces itself in back nav history', async t => {
|
||||
await loginAsFoobar(t)
|
||||
await t
|
||||
.click(notificationsNavButton)
|
||||
.expect(getUrl()).contains('/notifications')
|
||||
.navigateTo(SHARE_URL)
|
||||
.expect(getUrl()).eql('http://localhost:4002/')
|
||||
.expect(modalDialog.hasAttribute('aria-hidden')).notOk()
|
||||
.expect(composeModalInput.value).eql(SHARE_TEXT)
|
||||
.click(closeDialogButton)
|
||||
.expect(modalDialog.exists).notOk()
|
||||
await goBack()
|
||||
await t
|
||||
.expect(getUrl()).contains('/notifications')
|
||||
})
|
||||
|
||||
test('Share target does nothing when not logged in', async t => {
|
||||
await t
|
||||
.navigateTo(SHARE_URL)
|
||||
.expect(getUrl()).eql('http://localhost:4002/')
|
||||
.expect(modalDialog.exists).notOk()
|
||||
})
|
Loading…
Reference in a new issue