Add webpush front-end support
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
f1aac86bfb
commit
2c29a837ad
|
@ -83,6 +83,10 @@ export const CONFIG = gql`
|
|||
instanceFeeds {
|
||||
enabled
|
||||
}
|
||||
webPush {
|
||||
enabled
|
||||
publicKey
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -159,3 +163,14 @@ export const TIMEZONES = gql`
|
|||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const WEB_PUSH = gql`
|
||||
query {
|
||||
config {
|
||||
webPush {
|
||||
enabled
|
||||
publicKey
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import apolloProvider from "@/vue-apollo";
|
||||
import ApolloClient from "apollo-client";
|
||||
import { NormalizedCacheObject } from "apollo-cache-inmemory";
|
||||
import { WEB_PUSH } from "../graphql/config";
|
||||
import { IConfig } from "../types/config.model";
|
||||
|
||||
function urlBase64ToUint8Array(base64String: string): Uint8Array {
|
||||
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
|
||||
const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
|
||||
|
||||
const rawData = window.atob(base64);
|
||||
const outputArray = new Uint8Array(rawData.length);
|
||||
|
||||
for (let i = 0; i < rawData.length; ++i) {
|
||||
outputArray[i] = rawData.charCodeAt(i);
|
||||
}
|
||||
return outputArray;
|
||||
}
|
||||
|
||||
export async function subscribeUserToPush(): Promise<PushSubscription | null> {
|
||||
const registration = await navigator.serviceWorker.register(
|
||||
"/service-worker.js"
|
||||
);
|
||||
|
||||
const client = apolloProvider.defaultClient as ApolloClient<NormalizedCacheObject>;
|
||||
const { data } = await client.mutate<{ config: IConfig }>({
|
||||
mutation: WEB_PUSH,
|
||||
});
|
||||
|
||||
if (data?.config?.webPush?.enabled && data?.config?.webPush?.publicKey) {
|
||||
const subscribeOptions = {
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: urlBase64ToUint8Array(
|
||||
data?.config?.webPush?.publicKey
|
||||
),
|
||||
};
|
||||
const pushSubscription = await registration.pushManager.subscribe(
|
||||
subscribeOptions
|
||||
);
|
||||
console.log(
|
||||
"Received PushSubscription: ",
|
||||
JSON.stringify(pushSubscription)
|
||||
);
|
||||
return pushSubscription;
|
||||
}
|
||||
return null;
|
||||
}
|
|
@ -97,4 +97,8 @@ export interface IConfig {
|
|||
instanceFeeds: {
|
||||
enabled: boolean;
|
||||
};
|
||||
webPush: {
|
||||
enabled: boolean;
|
||||
publicKey: string;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,6 +15,16 @@
|
|||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<div class="setting-title">
|
||||
<h2>{{ $t("Participation notifications") }}</h2>
|
||||
</div>
|
||||
<b-button
|
||||
icon-left="rss"
|
||||
@click="subscribeToWebPush"
|
||||
v-if="!canShowWebPush"
|
||||
>{{ $t("WebPush") }}</b-button
|
||||
>
|
||||
<span v-else>{{ $t("You can't use webpush in this browser.") }}</span>
|
||||
<div class="setting-title">
|
||||
<h2>{{ $t("Participation notifications") }}</h2>
|
||||
</div>
|
||||
|
@ -202,6 +212,7 @@ import { IUser } from "../../types/current-user.model";
|
|||
import RouteName from "../../router/name";
|
||||
import { IFeedToken } from "@/types/feedtoken.model";
|
||||
import { CREATE_FEED_TOKEN, DELETE_FEED_TOKEN } from "@/graphql/feed_tokens";
|
||||
import { subscribeUserToPush } from "../../services/push-subscription";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
|
@ -305,6 +316,17 @@ export default class Notifications extends Vue {
|
|||
this.feedTokens.push(newToken);
|
||||
}
|
||||
|
||||
async subscribeToWebPush(): Promise<void> {
|
||||
if (window.isSecureContext && navigator.serviceWorker) {
|
||||
const a = await subscribeUserToPush();
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
|
||||
canShowWebPush(): boolean {
|
||||
return !!window.isSecureContext && !!navigator.serviceWorker;
|
||||
}
|
||||
|
||||
private async deleteFeedToken(token: string): Promise<void> {
|
||||
await this.$apollo.mutate({
|
||||
mutation: DELETE_FEED_TOKEN,
|
||||
|
|
|
@ -142,6 +142,11 @@ defmodule Mobilizon.GraphQL.Resolvers.Config do
|
|||
},
|
||||
instance_feeds: %{
|
||||
enabled: Config.get([:instance, :enable_instance_feeds])
|
||||
},
|
||||
web_push: %{
|
||||
enabled: !is_nil(Application.get_env(:web_push_encryption, :vapid_details)),
|
||||
public_key:
|
||||
get_in(Application.get_env(:web_push_encryption, :vapid_details), [:public_key])
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -64,6 +64,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
|||
|
||||
field(:auth, :auth, description: "The instance auth methods")
|
||||
field(:instance_feeds, :instance_feeds, description: "The instance's feed settings")
|
||||
field(:web_push, :web_push, description: "Web Push settings for the instance")
|
||||
end
|
||||
|
||||
@desc """
|
||||
|
@ -299,6 +300,11 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
|||
field(:enabled, :boolean, description: "Whether the instance-wide feeds are enabled")
|
||||
end
|
||||
|
||||
object :web_push do
|
||||
field(:enabled, :boolean, description: "Whether the WebPush feature is enabled")
|
||||
field(:public_key, :string, description: "The server's public WebPush VAPID key")
|
||||
end
|
||||
|
||||
object :config_queries do
|
||||
@desc "Get the instance config"
|
||||
field :config, :config do
|
||||
|
|
Loading…
Reference in New Issue