✨ Local Notifications
This commit is contained in:
parent
c3bfb2069c
commit
43aad8c2d2
@ -9,6 +9,7 @@ android {
|
|||||||
|
|
||||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation project(':capacitor-local-notifications')
|
||||||
implementation project(':capacitor-preferences')
|
implementation project(':capacitor-preferences')
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,5 +2,8 @@
|
|||||||
include ':capacitor-android'
|
include ':capacitor-android'
|
||||||
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||||
|
|
||||||
|
include ':capacitor-local-notifications'
|
||||||
|
project(':capacitor-local-notifications').projectDir = new File('../node_modules/@capacitor/local-notifications/android')
|
||||||
|
|
||||||
include ':capacitor-preferences'
|
include ':capacitor-preferences'
|
||||||
project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android')
|
project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android')
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
|
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
|
||||||
|
730477372BB91A4200A78988 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
|
||||||
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
|
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
|
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
@ -73,6 +74,7 @@
|
|||||||
504EC3061FED79650016851F /* App */ = {
|
504EC3061FED79650016851F /* App */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
730477372BB91A4200A78988 /* App.entitlements */,
|
||||||
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
||||||
504EC3071FED79650016851F /* AppDelegate.swift */,
|
504EC3071FED79650016851F /* AppDelegate.swift */,
|
||||||
504EC30B1FED79650016851F /* Main.storyboard */,
|
504EC30B1FED79650016851F /* Main.storyboard */,
|
||||||
@ -345,6 +347,7 @@
|
|||||||
baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */;
|
baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
@ -367,6 +370,7 @@
|
|||||||
baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */;
|
baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
12
ios/App/App/App.entitlements
Normal file
12
ios/App/App/App.entitlements
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>development</string>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>webcredentials:solsynth.dev</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -20,8 +20,21 @@
|
|||||||
<string>$(MARKETING_VERSION)</string>
|
<string>$(MARKETING_VERSION)</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string></string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>Allow Solian use your camera so that you can take photo for your post.</string>
|
||||||
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||||
|
<string>Allow Solian full access your photo library so that you can share photos more easily.</string>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>Allow Solian access your photo library so that you can share photos.</string>
|
||||||
|
<key>UIBackgroundModes</key>
|
||||||
|
<array>
|
||||||
|
<string>fetch</string>
|
||||||
|
<string>remote-notification</string>
|
||||||
|
</array>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
@ -43,15 +56,7 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<key>LSApplicationCategoryType</key>
|
|
||||||
<string></string>
|
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
|
||||||
<string>Allow Solian full access your photo library so that you can share photos more easily.</string>
|
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
|
||||||
<string>Allow Solian access your photo library so that you can share photos.</string>
|
|
||||||
<key>NSCameraUsageDescription</key>
|
|
||||||
<string>Allow Solian use your camera so that you can take photo for your post.</string>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -11,6 +11,7 @@ install! 'cocoapods', :disable_input_output_paths => true
|
|||||||
def capacitor_pods
|
def capacitor_pods
|
||||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||||
|
pod 'CapacitorLocalNotifications', :path => '../../node_modules/@capacitor/local-notifications'
|
||||||
pod 'CapacitorPreferences', :path => '../../node_modules/@capacitor/preferences'
|
pod 'CapacitorPreferences', :path => '../../node_modules/@capacitor/preferences'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2,12 +2,15 @@ PODS:
|
|||||||
- Capacitor (5.7.4):
|
- Capacitor (5.7.4):
|
||||||
- CapacitorCordova
|
- CapacitorCordova
|
||||||
- CapacitorCordova (5.7.4)
|
- CapacitorCordova (5.7.4)
|
||||||
|
- CapacitorLocalNotifications (5.0.7):
|
||||||
|
- Capacitor
|
||||||
- CapacitorPreferences (5.0.7):
|
- CapacitorPreferences (5.0.7):
|
||||||
- Capacitor
|
- Capacitor
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- "Capacitor (from `../../node_modules/@capacitor/ios`)"
|
- "Capacitor (from `../../node_modules/@capacitor/ios`)"
|
||||||
- "CapacitorCordova (from `../../node_modules/@capacitor/ios`)"
|
- "CapacitorCordova (from `../../node_modules/@capacitor/ios`)"
|
||||||
|
- "CapacitorLocalNotifications (from `../../node_modules/@capacitor/local-notifications`)"
|
||||||
- "CapacitorPreferences (from `../../node_modules/@capacitor/preferences`)"
|
- "CapacitorPreferences (from `../../node_modules/@capacitor/preferences`)"
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
@ -15,14 +18,17 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../../node_modules/@capacitor/ios"
|
:path: "../../node_modules/@capacitor/ios"
|
||||||
CapacitorCordova:
|
CapacitorCordova:
|
||||||
:path: "../../node_modules/@capacitor/ios"
|
:path: "../../node_modules/@capacitor/ios"
|
||||||
|
CapacitorLocalNotifications:
|
||||||
|
:path: "../../node_modules/@capacitor/local-notifications"
|
||||||
CapacitorPreferences:
|
CapacitorPreferences:
|
||||||
:path: "../../node_modules/@capacitor/preferences"
|
:path: "../../node_modules/@capacitor/preferences"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Capacitor: 4fe9adf012caceb4c71ffea2f1f4d005cdcbeea7
|
Capacitor: 4fe9adf012caceb4c71ffea2f1f4d005cdcbeea7
|
||||||
CapacitorCordova: a6e87fccc0307dee7aec1560ec9398485f2b0ce7
|
CapacitorCordova: a6e87fccc0307dee7aec1560ec9398485f2b0ce7
|
||||||
|
CapacitorLocalNotifications: c58afadd159f6bc540ef9b3cbdbc82510a2bf112
|
||||||
CapacitorPreferences: 77ac427e98db83bace772455f8ba447430382c4c
|
CapacitorPreferences: 77ac427e98db83bace772455f8ba447430382c4c
|
||||||
|
|
||||||
PODFILE CHECKSUM: 769e120bf4dfe4ef1095b83775e36bafeeeb3cdd
|
PODFILE CHECKSUM: 19c3106e1cb0c8c0ae26243bfb70b974f8cfaaf5
|
||||||
|
|
||||||
COCOAPODS: 1.15.1
|
COCOAPODS: 1.15.1
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"@capacitor/android": "^5.7.4",
|
"@capacitor/android": "^5.7.4",
|
||||||
"@capacitor/core": "^5.7.4",
|
"@capacitor/core": "^5.7.4",
|
||||||
"@capacitor/ios": "^5.7.4",
|
"@capacitor/ios": "^5.7.4",
|
||||||
|
"@capacitor/local-notifications": "^5.0.7",
|
||||||
"@capacitor/preferences": "^5.0.7",
|
"@capacitor/preferences": "^5.0.7",
|
||||||
"@fontsource/roboto": "^5.0.12",
|
"@fontsource/roboto": "^5.0.12",
|
||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-menu eager :close-on-content-click="false">
|
<v-menu eager :close-on-content-click="false">
|
||||||
<template #activator="{ props }">
|
<template #activator="{ props }">
|
||||||
<v-btn v-bind="props" icon rounded="circle" size="small" variant="text" :loading="loading">
|
<v-btn v-bind="props" icon size="small" variant="text" :loading="loading">
|
||||||
<v-badge v-if="pagination.total > 0" color="error" :content="pagination.total">
|
<v-badge v-if="notify.total > 0" color="error" :content="notify.total">
|
||||||
<v-icon icon="mdi-bell" />
|
<v-icon icon="mdi-bell" />
|
||||||
</v-badge>
|
</v-badge>
|
||||||
|
|
||||||
@ -10,20 +10,19 @@
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<v-list v-if="notifications.length <= 0" class="w-[380px]" density="compact">
|
<v-list v-if="notify.notifications.length <= 0" class="w-[380px]" density="compact">
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<v-alert class="text-sm" variant="tonal" type="info">You are done! There is no unread notifications for
|
<v-alert class="text-sm" variant="tonal" type="info">You are done! There is no unread notifications for you.</v-alert>
|
||||||
you.</v-alert>
|
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
|
|
||||||
<v-list v-else class="w-[380px]" density="compact" lines="three">
|
<v-list v-else class="w-[380px]" density="compact" lines="three">
|
||||||
<v-list-item v-for="item in notifications">
|
<v-list-item v-for="(item, idx) in notify.notifications">
|
||||||
<template #title>{{ item.subject }}</template>
|
<template #title>{{ item.subject }}</template>
|
||||||
<template #subtitle>{{ item.content }}</template>
|
<template #subtitle>{{ item.content }}</template>
|
||||||
|
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-btn icon="mdi-check" size="x-small" variant="text" :disabled="loading" @click="markAsRead(item)" />
|
<v-btn icon="mdi-check" size="x-small" variant="text" :disabled="loading" @click="markAsRead(item, idx)" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="flex text-xs gap-1">
|
<div class="flex text-xs gap-1">
|
||||||
@ -40,50 +39,32 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { request } from "@/scripts/request"
|
import { request } from "@/scripts/request"
|
||||||
import { getAtk } from "@/stores/userinfo"
|
import { getAtk } from "@/stores/userinfo"
|
||||||
import { reactive, ref } from "vue"
|
import { computed, onMounted, onUnmounted, ref } from "vue";
|
||||||
|
import { useNotifications } from "@/stores/notifications";
|
||||||
|
|
||||||
const loading = ref(false)
|
const notify = useNotifications()
|
||||||
|
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
|
const submitting = ref(false)
|
||||||
|
const loading = computed(() => notify.loading || submitting.value)
|
||||||
|
|
||||||
const notifications = ref<any[]>([])
|
async function markAsRead(item: any, idx: number) {
|
||||||
const pagination = reactive({ page: 1, pageSize: 25, total: 0 })
|
submitting.value = true
|
||||||
|
const res = await request(`/api/notifications/${item.id}/read`, {
|
||||||
async function readNotifications() {
|
|
||||||
loading.value = true
|
|
||||||
const res = await request(
|
|
||||||
"identity",
|
|
||||||
"/api/notifications?" +
|
|
||||||
new URLSearchParams({
|
|
||||||
take: pagination.pageSize.toString(),
|
|
||||||
offset: ((pagination.page - 1) * pagination.pageSize).toString()
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
headers: { Authorization: `Bearer ${await getAtk()}` }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (res.status === 200) {
|
|
||||||
const data = await res.json()
|
|
||||||
notifications.value = data["data"]
|
|
||||||
pagination.total = data["count"]
|
|
||||||
}
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
readNotifications()
|
|
||||||
|
|
||||||
async function markAsRead(item: any) {
|
|
||||||
loading.value = true
|
|
||||||
const res = await request("identity", `/api/notifications/${item.id}/read`, {
|
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: { Authorization: `Bearer ${await getAtk()}` }
|
headers: { Authorization: `Bearer ${getAtk()}` },
|
||||||
})
|
})
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
error.value = await res.text()
|
error.value = await res.text()
|
||||||
} else {
|
} else {
|
||||||
await readNotifications()
|
notify.remove(idx)
|
||||||
error.value = null
|
error.value = null
|
||||||
}
|
}
|
||||||
loading.value = false
|
submitting.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notify.list()
|
||||||
|
|
||||||
|
onMounted(() => notify.connect())
|
||||||
|
onUnmounted(() => notify.disconnect())
|
||||||
</script>
|
</script>
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
<v-carousel-item v-for="(item, idx) in attachments">
|
<v-carousel-item v-for="(item, idx) in attachments">
|
||||||
<img
|
<img
|
||||||
v-if="item.type === 1"
|
v-if="item.type === 1"
|
||||||
loading="lazy"
|
|
||||||
decoding="async"
|
decoding="async"
|
||||||
class="cursor-zoom-in content-visibility-auto w-full h-full object-contain"
|
class="cursor-zoom-in content-visibility-auto w-full h-full object-contain"
|
||||||
:src="getUrl(item)"
|
:src="getUrl(item)"
|
||||||
|
81
src/stores/notifications.ts
Normal file
81
src/stores/notifications.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { defineStore } from "pinia"
|
||||||
|
import { ref } from "vue"
|
||||||
|
import { checkLoggedIn, getAtk } from "@/stores/userinfo"
|
||||||
|
import { buildRequestUrl, request } from "@/scripts/request"
|
||||||
|
import { LocalNotifications } from "@capacitor/local-notifications"
|
||||||
|
import { Capacitor } from "@capacitor/core"
|
||||||
|
|
||||||
|
export const useNotifications = defineStore("notifications", () => {
|
||||||
|
let socket: WebSocket
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const notifications = ref<any[]>([])
|
||||||
|
const total = ref(0)
|
||||||
|
|
||||||
|
async function list() {
|
||||||
|
loading.value = true
|
||||||
|
const res = await request(
|
||||||
|
"identity",
|
||||||
|
"/api/notifications?" +
|
||||||
|
new URLSearchParams({
|
||||||
|
take: (25).toString(),
|
||||||
|
offset: (0).toString()
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
headers: { Authorization: `Bearer ${await getAtk()}` }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (res.status === 200) {
|
||||||
|
const data = await res.json()
|
||||||
|
notifications.value = data["data"]
|
||||||
|
total.value = data["count"]
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove(idx: number) {
|
||||||
|
notifications.value.splice(idx, 1)
|
||||||
|
total.value--
|
||||||
|
}
|
||||||
|
|
||||||
|
async function connect() {
|
||||||
|
if (!(await checkLoggedIn())) return
|
||||||
|
|
||||||
|
const uri = buildRequestUrl("identity", "/api/notifications/listen").replace("http", "ws")
|
||||||
|
|
||||||
|
socket = new WebSocket(uri + `?tk=${await getAtk() as string}`)
|
||||||
|
|
||||||
|
socket.addEventListener("open", (event) => {
|
||||||
|
console.log("[NOTIFICATIONS] The listen websocket has been established... ", event.type)
|
||||||
|
})
|
||||||
|
socket.addEventListener("close", (event) => {
|
||||||
|
console.warn("[NOTIFICATIONS] The listen websocket is disconnected... ", event.reason, event.code)
|
||||||
|
})
|
||||||
|
socket.addEventListener("message", (event) => {
|
||||||
|
const data = JSON.parse(event.data)
|
||||||
|
notifications.value.push(data)
|
||||||
|
total.value++
|
||||||
|
|
||||||
|
if (Capacitor.getPlatform() === "web") {
|
||||||
|
new Notification(data["id"], {
|
||||||
|
body: data["subject"]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
LocalNotifications.schedule({
|
||||||
|
notifications: [
|
||||||
|
{ id: data["id"], title: data["subject"], body: data["subject"] }
|
||||||
|
]
|
||||||
|
}).then((res) => console.log(res))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await Notification.requestPermission()
|
||||||
|
}
|
||||||
|
|
||||||
|
function disconnect() {
|
||||||
|
socket.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return { loading, notifications, total, list, remove, connect, disconnect }
|
||||||
|
})
|
@ -4,7 +4,7 @@
|
|||||||
<post-list v-model:posts="posts" :loader="readMore" />
|
<post-list v-model:posts="posts" :loader="readMore" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="aside md:sticky top-0 w-full h-fit md:min-w-[280px] md:max-w-[320px] max-md:order-first">
|
<div class="aside w-full h-full md:min-w-[320px] md:max-w-[320px] max-md:order-first">
|
||||||
<v-card title="Categories">
|
<v-card title="Categories">
|
||||||
<v-list density="compact">
|
<v-list density="compact">
|
||||||
<v-list-item title="All" prepend-icon="mdi-apps" active></v-list-item>
|
<v-list-item title="All" prepend-icon="mdi-apps" active></v-list-item>
|
||||||
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import PostList from "@/components/posts/PostList.vue"
|
import PostList from "@/components/posts/PostList.vue"
|
||||||
import { reactive, ref } from "vue"
|
|
||||||
import { request } from "@/scripts/request"
|
import { request } from "@/scripts/request"
|
||||||
|
import { reactive, ref } from "vue"
|
||||||
|
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
||||||
|
@ -16,9 +16,8 @@ export default defineConfig({
|
|||||||
registerType: "autoUpdate",
|
registerType: "autoUpdate",
|
||||||
useCredentials: true,
|
useCredentials: true,
|
||||||
manifest: {
|
manifest: {
|
||||||
name: "Solar Network",
|
name: "Solian",
|
||||||
short_name: "Solian",
|
description: "The Solar Network Application",
|
||||||
description: "The Solar Network entrypoint.",
|
|
||||||
theme_color: "#4b5094",
|
theme_color: "#4b5094",
|
||||||
display: "standalone",
|
display: "standalone",
|
||||||
icons: [
|
icons: [
|
||||||
@ -27,9 +26,13 @@ export default defineConfig({
|
|||||||
sizes: "1024x1024",
|
sizes: "1024x1024",
|
||||||
type: "image/png",
|
type: "image/png",
|
||||||
purpose: "maskable"
|
purpose: "maskable"
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
workbox: {
|
||||||
|
sourcemap: true,
|
||||||
|
cleanupOutdatedCaches: true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
|
Reference in New Issue
Block a user