app work
This commit is contained in:
parent
d4d9065781
commit
a0291b40b2
|
@ -0,0 +1,3 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<bytecodeTargetLevel target="11" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RemoteRepositoriesConfiguration">
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Maven Central repository" />
|
||||||
|
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="jboss.community" />
|
||||||
|
<option name="name" value="JBoss Community repository" />
|
||||||
|
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="MavenRepo" />
|
||||||
|
<option name="name" value="MavenRepo" />
|
||||||
|
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="Google" />
|
||||||
|
<option name="name" value="Google" />
|
||||||
|
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="maven" />
|
||||||
|
<option name="name" value="maven" />
|
||||||
|
<option name="url" value="https://maven.google.com" />
|
||||||
|
</remote-repository>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectType">
|
||||||
|
<option name="id" value="Android" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -9,10 +9,15 @@ android {
|
||||||
|
|
||||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation project(':capacitor-app')
|
||||||
|
implementation project(':capacitor-camera')
|
||||||
|
implementation project(':capacitor-device')
|
||||||
|
implementation project(':capacitor-preferences')
|
||||||
|
implementation project(':capacitor-push-notifications')
|
||||||
|
implementation project(':capacitor-status-bar')
|
||||||
|
implementation "com.onesignal:OneSignal:4.8.5"
|
||||||
}
|
}
|
||||||
|
apply from: "../../../../node_modules/.pnpm/onesignal-cordova-plugin@3.3.1/node_modules/onesignal-cordova-plugin/build-extras-onesignal.gradle"
|
||||||
|
|
||||||
if (hasProperty('postBuildExtras')) {
|
if (hasProperty('postBuildExtras')) {
|
||||||
postBuildExtras()
|
postBuildExtras()
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
package org.calckey.app;
|
package org.calckey.app;
|
||||||
|
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.webkit.WebSettings;
|
||||||
|
|
||||||
import com.getcapacitor.BridgeActivity;
|
import com.getcapacitor.BridgeActivity;
|
||||||
|
import com.getcapacitor.Plugin;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class MainActivity extends BridgeActivity {
|
public class MainActivity extends BridgeActivity {
|
||||||
void setDarkMode() {
|
void setDarkMode() {
|
||||||
|
@ -34,15 +41,4 @@ public class MainActivity extends BridgeActivity {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
setDarkMode();
|
setDarkMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
// Initializes the Bridge
|
|
||||||
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
|
|
||||||
// Additional plugins you've installed go here
|
|
||||||
// Ex: add(TotallyAwesomePlugin.class);
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||||
include ':capacitor-android'
|
include ':capacitor-android'
|
||||||
project(':capacitor-android').projectDir = new File('../../../node_modules/.pnpm/@capacitor+android@4.7.3_@capacitor+core@4.7.3/node_modules/@capacitor/android/capacitor')
|
project(':capacitor-android').projectDir = new File('../../../node_modules/.pnpm/@capacitor+android@4.7.3_@capacitor+core@4.7.3/node_modules/@capacitor/android/capacitor')
|
||||||
|
|
||||||
|
include ':capacitor-app'
|
||||||
|
project(':capacitor-app').projectDir = new File('../../../node_modules/.pnpm/@capacitor+app@4.1.1_@capacitor+core@4.7.3/node_modules/@capacitor/app/android')
|
||||||
|
|
||||||
|
include ':capacitor-camera'
|
||||||
|
project(':capacitor-camera').projectDir = new File('../../../node_modules/.pnpm/@capacitor+camera@4.1.4_@capacitor+core@4.7.3/node_modules/@capacitor/camera/android')
|
||||||
|
|
||||||
|
include ':capacitor-device'
|
||||||
|
project(':capacitor-device').projectDir = new File('../../../node_modules/.pnpm/@capacitor+device@4.1.0_@capacitor+core@4.7.3/node_modules/@capacitor/device/android')
|
||||||
|
|
||||||
|
include ':capacitor-preferences'
|
||||||
|
project(':capacitor-preferences').projectDir = new File('../../../node_modules/.pnpm/@capacitor+preferences@4.0.2_@capacitor+core@4.7.3/node_modules/@capacitor/preferences/android')
|
||||||
|
|
||||||
|
include ':capacitor-push-notifications'
|
||||||
|
project(':capacitor-push-notifications').projectDir = new File('../../../node_modules/.pnpm/@capacitor+push-notifications@4.1.2_@capacitor+core@4.7.3/node_modules/@capacitor/push-notifications/android')
|
||||||
|
|
||||||
|
include ':capacitor-status-bar'
|
||||||
|
project(':capacitor-status-bar').projectDir = new File('../../../node_modules/.pnpm/@capacitor+status-bar@4.1.1_@capacitor+core@4.7.3/node_modules/@capacitor/status-bar/android')
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
<string>$(PRODUCT_NAME)</string>
|
<string>$(PRODUCT_NAME)</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
|
<key>UIBackgroundModes</key>
|
||||||
|
<array>
|
||||||
|
<string>remote-notification</string>
|
||||||
|
</array>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>$(MARKETING_VERSION)</string>
|
<string>$(MARKETING_VERSION)</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
|
|
|
@ -11,7 +11,13 @@ install! 'cocoapods', :disable_input_output_paths => true
|
||||||
def capacitor_pods
|
def capacitor_pods
|
||||||
pod 'Capacitor', :path => '../../../../node_modules/.pnpm/@capacitor+ios@4.7.3_@capacitor+core@4.7.3/node_modules/@capacitor/ios'
|
pod 'Capacitor', :path => '../../../../node_modules/.pnpm/@capacitor+ios@4.7.3_@capacitor+core@4.7.3/node_modules/@capacitor/ios'
|
||||||
pod 'CapacitorCordova', :path => '../../../../node_modules/.pnpm/@capacitor+ios@4.7.3_@capacitor+core@4.7.3/node_modules/@capacitor/ios'
|
pod 'CapacitorCordova', :path => '../../../../node_modules/.pnpm/@capacitor+ios@4.7.3_@capacitor+core@4.7.3/node_modules/@capacitor/ios'
|
||||||
|
pod 'CapacitorApp', :path => '../../../../node_modules/.pnpm/@capacitor+app@4.1.1_@capacitor+core@4.7.3/node_modules/@capacitor/app'
|
||||||
|
pod 'CapacitorCamera', :path => '../../../../node_modules/.pnpm/@capacitor+camera@4.1.4_@capacitor+core@4.7.3/node_modules/@capacitor/camera'
|
||||||
|
pod 'CapacitorDevice', :path => '../../../../node_modules/.pnpm/@capacitor+device@4.1.0_@capacitor+core@4.7.3/node_modules/@capacitor/device'
|
||||||
|
pod 'CapacitorPreferences', :path => '../../../../node_modules/.pnpm/@capacitor+preferences@4.0.2_@capacitor+core@4.7.3/node_modules/@capacitor/preferences'
|
||||||
|
pod 'CapacitorPushNotifications', :path => '../../../../node_modules/.pnpm/@capacitor+push-notifications@4.1.2_@capacitor+core@4.7.3/node_modules/@capacitor/push-notifications'
|
||||||
|
pod 'CapacitorStatusBar', :path => '../../../../node_modules/.pnpm/@capacitor+status-bar@4.1.1_@capacitor+core@4.7.3/node_modules/@capacitor/status-bar'
|
||||||
|
pod 'CordovaPluginsStatic', :path => '../capacitor-cordova-ios-plugins'
|
||||||
end
|
end
|
||||||
|
|
||||||
target 'App' do
|
target 'App' do
|
||||||
|
|
|
@ -95,6 +95,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capacitor/android": "^4.7.3",
|
"@capacitor/android": "^4.7.3",
|
||||||
"@capacitor/app": "^4.1.1",
|
"@capacitor/app": "^4.1.1",
|
||||||
|
"@capacitor/camera": "^4.1.4",
|
||||||
"@capacitor/core": "^4.7.3",
|
"@capacitor/core": "^4.7.3",
|
||||||
"@capacitor/device": "^4.1.0",
|
"@capacitor/device": "^4.1.0",
|
||||||
"@capacitor/ios": "^4.7.3",
|
"@capacitor/ios": "^4.7.3",
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { showSuspendedDialog } from "./scripts/show-suspended-dialog";
|
||||||
import { i18n } from "./i18n";
|
import { i18n } from "./i18n";
|
||||||
import { del, get, set } from "@/scripts/idb-proxy";
|
import { del, get, set } from "@/scripts/idb-proxy";
|
||||||
// #v-ifdef VITE_CAPACITOR
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
// #v-else
|
// #v-else
|
||||||
import { apiUrl } from "@/config";
|
import { apiUrl } from "@/config";
|
||||||
// #v-endif
|
// #v-endif
|
||||||
|
@ -44,6 +45,7 @@ export async function signout() {
|
||||||
|
|
||||||
const accounts = await getAccounts();
|
const accounts = await getAccounts();
|
||||||
// #v-ifdef VITE_CAPACITOR
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
// #v-else
|
// #v-else
|
||||||
//#region Remove service worker registration
|
//#region Remove service worker registration
|
||||||
try {
|
try {
|
||||||
|
@ -117,7 +119,32 @@ export async function removeAccount(id: Account["id"]) {
|
||||||
if (accounts.length > 0) await set("accounts", accounts);
|
if (accounts.length > 0) await set("accounts", accounts);
|
||||||
else await del("accounts");
|
else await del("accounts");
|
||||||
}
|
}
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
function fetchAccount(
|
||||||
|
token: string,
|
||||||
|
instanceUrl: string
|
||||||
|
): Promise<Account & { instanceUrl: string }> {
|
||||||
|
return new misskey.api.APIClient({ origin: instanceUrl, credential: token })
|
||||||
|
.request("i")
|
||||||
|
.then((res) => {
|
||||||
|
return { ...(res as Account), token, instanceUrl };
|
||||||
|
})
|
||||||
|
.catch((res) => {
|
||||||
|
if (res.error.id === "a8c724b3-6e9c-4b46-b1a8-bc3ed6258370") {
|
||||||
|
showSuspendedDialog().then(() => {
|
||||||
|
signout();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alert({
|
||||||
|
type: "error",
|
||||||
|
title: i18n.ts.failedToFetchAccountInformation,
|
||||||
|
text: JSON.stringify(res.error),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.reject(res);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// #v-else
|
||||||
function fetchAccount(token: string): Promise<Account> {
|
function fetchAccount(token: string): Promise<Account> {
|
||||||
return new Promise((done, fail) => {
|
return new Promise((done, fail) => {
|
||||||
// Fetch user
|
// Fetch user
|
||||||
|
@ -149,32 +176,7 @@ function fetchAccount(token: string): Promise<Account> {
|
||||||
.catch(fail);
|
.catch(fail);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// #v-endif
|
||||||
function fetchAccount(
|
|
||||||
token: string,
|
|
||||||
instanceUrl: string
|
|
||||||
): Promise<Account & { instanceUrl: string }> {
|
|
||||||
return new misskey.api.APIClient({ origin: instanceUrl, credential: token })
|
|
||||||
.request("i")
|
|
||||||
.then((res) => {
|
|
||||||
return { ...(res as Account), token, instanceUrl };
|
|
||||||
})
|
|
||||||
.catch((res) => {
|
|
||||||
if (res.error.id === "a8c724b3-6e9c-4b46-b1a8-bc3ed6258370") {
|
|
||||||
showSuspendedDialog().then(() => {
|
|
||||||
signout();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
alert({
|
|
||||||
type: "error",
|
|
||||||
title: i18n.ts.failedToFetchAccountInformation,
|
|
||||||
text: JSON.stringify(res.error),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Promise.reject(res);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateAccount(accountData: Object) {
|
export function updateAccount(accountData: Object) {
|
||||||
for (const [key, value] of Object.entries(accountData)) {
|
for (const [key, value] of Object.entries(accountData)) {
|
||||||
$i[key] = value;
|
$i[key] = value;
|
||||||
|
@ -325,11 +327,30 @@ export async function openAccountMenu(
|
||||||
const accountItemPromises = storedAccounts.map(
|
const accountItemPromises = storedAccounts.map(
|
||||||
(a) =>
|
(a) =>
|
||||||
new Promise((res) => {
|
new Promise((res) => {
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
const client = new misskey.api.APIClient({
|
||||||
|
origin: a.instanceUrl,
|
||||||
|
credential: a.token,
|
||||||
|
});
|
||||||
|
client
|
||||||
|
.request("users/show", {
|
||||||
|
userIds: [a.id],
|
||||||
|
})
|
||||||
|
.then((accounts) => {
|
||||||
|
const account = accounts.find((x) => x.id === a.id);
|
||||||
|
if (account == null) return res(null);
|
||||||
|
|
||||||
|
client.request("meta").then((meta) => {
|
||||||
|
res(createItem({ ...account, host: meta.name }));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// #v-else
|
||||||
accountsPromise.then((accounts) => {
|
accountsPromise.then((accounts) => {
|
||||||
const account = accounts.find((x) => x.id === a.id);
|
const account = accounts.find((x) => x.id === a.id);
|
||||||
if (account == null) return res(null);
|
if (account == null) return res(null);
|
||||||
res(createItem(account));
|
res(createItem(account));
|
||||||
});
|
});
|
||||||
|
// #v-endif
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -357,12 +378,16 @@ export async function openAccountMenu(
|
||||||
showSigninDialog();
|
showSigninDialog();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
{
|
{
|
||||||
text: i18n.ts.createAccount,
|
text: i18n.ts.createAccount,
|
||||||
action: () => {
|
action: () => {
|
||||||
createAccount();
|
createAccount();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// #v-endif
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<MkA v-if="url.startsWith('/')" v-user-preview="canonical" class="akbvjaqn" :class="{ isMe }" :to="url" :style="{ background: bgCss }" @click.stop>
|
<MkA v-if="url.startsWith('/')" v-user-preview="canonical" class="akbvjaqn" :class="{ isMe }" :to="url" :style="{ background: bgCss }" @click.stop>
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
<img
|
||||||
|
:class="$style.icon"
|
||||||
|
:src="`${$i.instanceUrl}/avatar/@${username}@${host}`"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
// #v-else
|
||||||
<img class="icon" :src="`/avatar/@${username}@${host}`" alt="">
|
<img class="icon" :src="`/avatar/@${username}@${host}`" alt="">
|
||||||
|
// #v-endif
|
||||||
<span class="main">
|
<span class="main">
|
||||||
<span class="username">@{{ username }}</span>
|
<span class="username">@{{ username }}</span>
|
||||||
<span v-if="(host != localHost) || $store.state.showFullAcct" class="host">@{{ toUnicode(host) }}</span>
|
<span v-if="(host != localHost) || $store.state.showFullAcct" class="host">@{{ toUnicode(host) }}</span>
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
</a>
|
</a>
|
||||||
<button v-else-if="item.type === 'user' && !items.hidden" :tabindex="i" class="_button item" :class="{ active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
<button v-else-if="item.type === 'user' && !items.hidden" :tabindex="i" class="_button item" :class="{ active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
||||||
<MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/>
|
<MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/>
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
[{{ item.user.host }}]
|
||||||
|
// #v-endif
|
||||||
<span v-if="item.indicate" class="indicator"><i class="ph-circle ph-fill"></i></span>
|
<span v-if="item.indicate" class="indicator"><i class="ph-circle ph-fill"></i></span>
|
||||||
</button>
|
</button>
|
||||||
<span v-else-if="item.type === 'switch'" :tabindex="i" class="item" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
<span v-else-if="item.type === 'switch'" :tabindex="i" class="item" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
||||||
|
|
|
@ -1,4 +1,56 @@
|
||||||
<template>
|
<template>
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
<form class="eppvobhk" :class="{ signing }" @submit.prevent="onSubmit">
|
||||||
|
<div class="normal-signin">
|
||||||
|
{{ i18n.ts.ririca.instance }}
|
||||||
|
<MkSelect v-model="instanceUrl" large :model-value="instances[0]?.url">
|
||||||
|
<option value="other">
|
||||||
|
{{ i18n.ts.ririca.selectInstanceYourself }}
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
v-for="(instance, i) in instances"
|
||||||
|
:key="instance.url"
|
||||||
|
:value="instance.url"
|
||||||
|
:selected="i === 0"
|
||||||
|
>
|
||||||
|
{{ instance.name }}
|
||||||
|
</option>
|
||||||
|
</MkSelect>
|
||||||
|
<template v-if="instanceUrl === 'other'">
|
||||||
|
URL
|
||||||
|
<MkInput
|
||||||
|
v-model="instanceUrlOther"
|
||||||
|
:spellcheck="false"
|
||||||
|
autofocus
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
{{ i18n.ts.ririca.accessToken }}
|
||||||
|
<MkInput
|
||||||
|
v-model="token"
|
||||||
|
:spellcheck="false"
|
||||||
|
autofocus
|
||||||
|
required
|
||||||
|
data-cy-signin-username
|
||||||
|
></MkInput>
|
||||||
|
<MkButton
|
||||||
|
class="_formBlock"
|
||||||
|
type="submit"
|
||||||
|
primary
|
||||||
|
:disabled="signing"
|
||||||
|
style="margin: 0 auto"
|
||||||
|
>
|
||||||
|
{{ signing ? i18n.ts.loggingIn : i18n.ts.login }}
|
||||||
|
</MkButton>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; justify-content: center"></div>
|
||||||
|
<a
|
||||||
|
href="https://misskey.io/notes/99l9jqqun2"
|
||||||
|
target="_blank"
|
||||||
|
style="color: var(--link); text-align: center"
|
||||||
|
>{{ i18n.ts.ririca.howToCreateToken }}</a>
|
||||||
|
</form>
|
||||||
|
// #v-else
|
||||||
<form class="eppvobhk _monolithic_" :class="{ signing, totpLogin }" @submit.prevent="onSubmit">
|
<form class="eppvobhk _monolithic_" :class="{ signing, totpLogin }" @submit.prevent="onSubmit">
|
||||||
<div class="auth _section _formRoot">
|
<div class="auth _section _formRoot">
|
||||||
<div v-show="withAvatar" class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null, marginBottom: message ? '1.5em' : null }"></div>
|
<div v-show="withAvatar" class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null, marginBottom: message ? '1.5em' : null }"></div>
|
||||||
|
@ -46,9 +98,11 @@
|
||||||
<a v-if="meta && meta.enableDiscordIntegration" class="_borderButton _gap" :href="`${apiUrl}/signin/discord`"><i class="ph-discord-logo ph-bold ph-lg" style="margin-right: 4px;"></i>{{ i18n.t('signinWith', { x: 'Discord' }) }}</a>
|
<a v-if="meta && meta.enableDiscordIntegration" class="_borderButton _gap" :href="`${apiUrl}/signin/discord`"><i class="ph-discord-logo ph-bold ph-lg" style="margin-right: 4px;"></i>{{ i18n.t('signinWith', { x: 'Discord' }) }}</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
// #v-endif
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import MkSelect from "@/components/form/select.vue";
|
||||||
import { defineAsyncComponent } from 'vue';
|
import { defineAsyncComponent } from 'vue';
|
||||||
import { toUnicode } from 'punycode/';
|
import { toUnicode } from 'punycode/';
|
||||||
import { showSuspendedDialog } from '../scripts/show-suspended-dialog';
|
import { showSuspendedDialog } from '../scripts/show-suspended-dialog';
|
||||||
|
@ -67,14 +121,23 @@ let user = $ref(null);
|
||||||
let username = $ref('');
|
let username = $ref('');
|
||||||
let password = $ref('');
|
let password = $ref('');
|
||||||
let token = $ref('');
|
let token = $ref('');
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
let host = $ref(toUnicode(configHost));
|
let host = $ref(toUnicode(configHost));
|
||||||
let totpLogin = $ref(false);
|
let totpLogin = $ref(false);
|
||||||
|
// #v-endif
|
||||||
let credential = $ref(null);
|
let credential = $ref(null);
|
||||||
let challengeData = $ref(null);
|
let challengeData = $ref(null);
|
||||||
let queryingKey = $ref(false);
|
let queryingKey = $ref(false);
|
||||||
let hCaptchaResponse = $ref(null);
|
let hCaptchaResponse = $ref(null);
|
||||||
let reCaptchaResponse = $ref(null);
|
let reCaptchaResponse = $ref(null);
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
const instanceUrl = $ref("");
|
||||||
|
const instanceUrlOther = $ref("");
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
const meta = $computed(() => instance);
|
const meta = $computed(() => instance);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -111,10 +174,24 @@ function onUsernameChange() {
|
||||||
|
|
||||||
function onLogin(res) {
|
function onLogin(res) {
|
||||||
if (props.autoSet) {
|
if (props.autoSet) {
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
return login(res.i, res.instance);
|
||||||
|
// #v-else
|
||||||
return login(res.i);
|
return login(res.i);
|
||||||
|
// #v-endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
const instanceUrlResult = $computed(() => {
|
||||||
|
if (instanceUrl === "other") {
|
||||||
|
// うっかりhttps://を入れてもreplaceされるから大丈夫
|
||||||
|
// new URL.origin
|
||||||
|
return new URL("https://" + instanceUrlOther.replace("https://", ""))
|
||||||
|
.origin;
|
||||||
|
}
|
||||||
|
return "https://" + instanceUrl;
|
||||||
|
});
|
||||||
|
// #v-endif
|
||||||
function queryKey() {
|
function queryKey() {
|
||||||
queryingKey = true;
|
queryingKey = true;
|
||||||
return navigator.credentials.get({
|
return navigator.credentials.get({
|
||||||
|
@ -145,8 +222,13 @@ function queryKey() {
|
||||||
'g-recaptcha-response': reCaptchaResponse,
|
'g-recaptcha-response': reCaptchaResponse,
|
||||||
});
|
});
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
emit("login", { ...res, instance: instanceUrl });
|
||||||
|
return onLogin({ ...res, instance: instanceUrl });
|
||||||
|
// #v-else
|
||||||
emit('login', res);
|
emit('login', res);
|
||||||
return onLogin(res);
|
return onLogin(res);
|
||||||
|
// #v-endif
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
if (err === null) return;
|
if (err === null) return;
|
||||||
os.alert({
|
os.alert({
|
||||||
|
@ -160,6 +242,11 @@ function queryKey() {
|
||||||
function onSubmit() {
|
function onSubmit() {
|
||||||
signing = true;
|
signing = true;
|
||||||
console.log('submit');
|
console.log('submit');
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
if (!token.valueOf()) {
|
||||||
|
login(token, instanceUrlResult);
|
||||||
|
signing = false;
|
||||||
|
// #v-else
|
||||||
if (!totpLogin && user && user.twoFactorEnabled) {
|
if (!totpLogin && user && user.twoFactorEnabled) {
|
||||||
if (window.PublicKeyCredential && user.securityKeys) {
|
if (window.PublicKeyCredential && user.securityKeys) {
|
||||||
os.api('signin', {
|
os.api('signin', {
|
||||||
|
@ -188,6 +275,7 @@ function onSubmit() {
|
||||||
emit('login', res);
|
emit('login', res);
|
||||||
onLogin(res);
|
onLogin(res);
|
||||||
}).catch(loginFailed);
|
}).catch(loginFailed);
|
||||||
|
// #v-endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +328,15 @@ function resetPassword() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
||||||
}, 'closed');
|
}, 'closed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
let instances = $ref([]);
|
||||||
|
fetch("https://api.calckey.org/instances.json").then((res) => {
|
||||||
|
res.json().then((data) => {
|
||||||
|
instances = data.instancesInfos;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// #v-endif
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<img v-if="customEmoji" class="mk-emoji custom" :class="{ normal, noStyle }" :src="url" :alt="alt" :title="alt" decoding="async"/>
|
<img v-if="customEmoji" class="mk-emoji custom" :class="{ normal, noStyle }" :src="url" :alt="alt" :title="alt" decoding="async"/>
|
||||||
<img v-else-if="char && !useOsNativeEmojis" class="mk-emoji" :src="url" :alt="alt" :title="alt" decoding="async"/>
|
<img v-else-if="char && !useOsNativeEmojis" class="mk-emoji"
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
:src="char2path(char)"
|
||||||
|
// #v-else
|
||||||
|
:src="url"
|
||||||
|
// #v-endif
|
||||||
|
:alt="alt" :title="alt" decoding="async"/>
|
||||||
<span v-else-if="char && useOsNativeEmojis">{{ char }}</span>
|
<span v-else-if="char && useOsNativeEmojis">{{ char }}</span>
|
||||||
<span v-else>{{ emoji }}</span>
|
<span v-else>{{ emoji }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
@ -12,6 +18,7 @@ import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||||
import { char2filePath } from '@/scripts/twemoji-base';
|
import { char2filePath } from '@/scripts/twemoji-base';
|
||||||
import { defaultStore } from '@/store';
|
import { defaultStore } from '@/store';
|
||||||
import { instance } from '@/instance';
|
import { instance } from '@/instance';
|
||||||
|
import { url as instanceUrl } from "@/config";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
emoji: string;
|
emoji: string;
|
||||||
|
@ -28,7 +35,10 @@ const ce = computed(() => props.customEmojis ?? instance.emojis ?? []);
|
||||||
const customEmoji = computed(() => isCustom.value ? ce.value.find(x => x.name === props.emoji.substr(1, props.emoji.length - 2)) : null);
|
const customEmoji = computed(() => isCustom.value ? ce.value.find(x => x.name === props.emoji.substr(1, props.emoji.length - 2)) : null);
|
||||||
const url = computed(() => {
|
const url = computed(() => {
|
||||||
if (char.value) {
|
if (char.value) {
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
// #v-else
|
||||||
return char2filePath(char.value);
|
return char2filePath(char.value);
|
||||||
|
// #v-endif
|
||||||
} else {
|
} else {
|
||||||
return defaultStore.state.disableShowingAnimatedImages
|
return defaultStore.state.disableShowingAnimatedImages
|
||||||
? getStaticImageUrl(customEmoji.value.url)
|
? getStaticImageUrl(customEmoji.value.url)
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
|
import { $i } from "@/account";
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
const address = $i ? new URL($i.instanceUrl) : null;
|
||||||
|
// #v-else
|
||||||
const address = new URL(location.href);
|
const address = new URL(location.href);
|
||||||
|
// #v-endif
|
||||||
const siteName = (
|
const siteName = (
|
||||||
document.querySelector('meta[property="og:site_name"]') as HTMLMetaElement
|
document.querySelector('meta[property="og:site_name"]') as HTMLMetaElement
|
||||||
)?.content;
|
)?.content;
|
||||||
|
|
||||||
export const host = address.host;
|
export const host = address?.host;
|
||||||
export const hostname = address.hostname;
|
export const hostname = address?.hostname;
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
export const url = $i?.instanceUrl;
|
||||||
|
// #v-else
|
||||||
export const url = address.origin;
|
export const url = address.origin;
|
||||||
|
// #v-endif
|
||||||
export const apiUrl = `${url}/api`;
|
export const apiUrl = `${url}/api`;
|
||||||
export const wsUrl = `${url
|
export const wsUrl = `${url
|
||||||
.replace("http://", "ws://")
|
.replace("http://", "ws://")
|
||||||
|
|
|
@ -50,10 +50,11 @@ import { reloadChannel } from "@/scripts/unison-reload";
|
||||||
import { reactionPicker } from "@/scripts/reaction-picker";
|
import { reactionPicker } from "@/scripts/reaction-picker";
|
||||||
import { getUrlWithoutLoginId } from "@/scripts/login-id";
|
import { getUrlWithoutLoginId } from "@/scripts/login-id";
|
||||||
import { getAccountFromId } from "@/scripts/get-account-from-id";
|
import { getAccountFromId } from "@/scripts/get-account-from-id";
|
||||||
import { Device } from "@capacitor/device";
|
import { Device, DeviceInfo } from "@capacitor/device";
|
||||||
import { App } from "@capacitor/app";
|
import { App } from "@capacitor/app";
|
||||||
import lightTheme from "@/themes/_light.json5";
|
import lightThemeDefault from "@/themes/_light.json5";
|
||||||
export let storedDeviceInfo: Object;
|
import OneSignal from "onesignal-cordova-plugin";
|
||||||
|
export let storedDeviceInfo: DeviceInfo;
|
||||||
// #v-ifdef VITE_CAPACITOR
|
// #v-ifdef VITE_CAPACITOR
|
||||||
const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
// #v-endif
|
// #v-endif
|
||||||
|
@ -122,7 +123,7 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
|
|
||||||
let isMobileApp = false;
|
let isMobileApp = false;
|
||||||
// #v-ifdef VITE_CAPACITOR
|
// #v-ifdef VITE_CAPACITOR
|
||||||
isMobileApp = false;
|
isMobileApp = true;
|
||||||
// #v-endif
|
// #v-endif
|
||||||
|
|
||||||
// If mobile, insert the viewport meta tag
|
// If mobile, insert the viewport meta tag
|
||||||
|
@ -214,11 +215,13 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log("not signed in");
|
console.log("not signed in");
|
||||||
}
|
}
|
||||||
applyTheme(lightTheme);
|
applyTheme(lightThemeDefault);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
const fetchInstanceMetaPromise = fetchInstance();
|
const fetchInstanceMetaPromise = fetchInstance();
|
||||||
|
|
||||||
fetchInstanceMetaPromise.then(() => {
|
fetchInstanceMetaPromise.then(() => {
|
||||||
|
@ -227,7 +230,7 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
// Init service worker
|
// Init service worker
|
||||||
initializeSw();
|
initializeSw();
|
||||||
});
|
});
|
||||||
|
// #v-endif
|
||||||
const app = createApp(
|
const app = createApp(
|
||||||
window.location.search === "?zen"
|
window.location.search === "?zen"
|
||||||
? defineAsyncComponent(() => import("@/ui/zen.vue"))
|
? defineAsyncComponent(() => import("@/ui/zen.vue"))
|
||||||
|
@ -287,7 +290,11 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
window.onerror = null;
|
window.onerror = null;
|
||||||
window.onunhandledrejection = null;
|
window.onunhandledrejection = null;
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
reactionPicker.init();
|
reactionPicker.init();
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
if (splash) {
|
if (splash) {
|
||||||
splash.style.opacity = "0";
|
splash.style.opacity = "0";
|
||||||
|
@ -325,6 +332,45 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
App.addListener("backButton", (canGoBack) => {
|
||||||
|
if (canGoBack) {
|
||||||
|
history.back();
|
||||||
|
} else {
|
||||||
|
App.exitApp();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
async function afterLoginSetup() {
|
||||||
|
if (!$i) return;
|
||||||
|
const hotkeys = {
|
||||||
|
d: (): void => {
|
||||||
|
defaultStore.set("darkMode", !defaultStore.state.darkMode);
|
||||||
|
},
|
||||||
|
s: search,
|
||||||
|
["p|n"]: post,
|
||||||
|
};
|
||||||
|
|
||||||
|
//shortcut
|
||||||
|
document.addEventListener("keydown", makeHotkey(hotkeys));
|
||||||
|
reactionPicker.init();
|
||||||
|
const fetchInstanceMetaPromise = fetchInstance();
|
||||||
|
|
||||||
|
fetchInstanceMetaPromise.then(() => {
|
||||||
|
localStorage.setItem("v", instance.version);
|
||||||
|
|
||||||
|
// Init service worker
|
||||||
|
initializeSw();
|
||||||
|
});
|
||||||
|
|
||||||
|
applyTheme(
|
||||||
|
defaultStore.reactiveState.darkMode.value ?
|
||||||
|
ColdDeviceStorage.get("darkTheme") :
|
||||||
|
ColdDeviceStorage.get("lightTheme")
|
||||||
|
)
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため)
|
// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため)
|
||||||
watch(
|
watch(
|
||||||
defaultStore.reactiveState.darkMode,
|
defaultStore.reactiveState.darkMode,
|
||||||
|
@ -365,6 +411,9 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
});
|
});
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
fetchInstanceMetaPromise.then(() => {
|
fetchInstanceMetaPromise.then(() => {
|
||||||
if (defaultStore.state.themeInitial) {
|
if (defaultStore.state.themeInitial) {
|
||||||
if (instance.defaultLightTheme != null)
|
if (instance.defaultLightTheme != null)
|
||||||
|
@ -380,6 +429,7 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
defaultStore.set("themeInitial", false);
|
defaultStore.set("themeInitial", false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
defaultStore.reactiveState.useBlurEffectForModal,
|
defaultStore.reactiveState.useBlurEffectForModal,
|
||||||
|
@ -436,12 +486,16 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
const hotkeys = {
|
const hotkeys = {
|
||||||
d: (): void => {
|
d: (): void => {
|
||||||
defaultStore.set("darkMode", !defaultStore.state.darkMode);
|
defaultStore.set("darkMode", !defaultStore.state.darkMode);
|
||||||
},
|
},
|
||||||
s: search,
|
s: search,
|
||||||
};
|
};
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
if ($i) {
|
if ($i) {
|
||||||
// only add post shortcuts if logged in
|
// only add post shortcuts if logged in
|
||||||
|
@ -544,6 +598,45 @@ const onesignal_app_id = "efe09597-0778-4156-97b7-0bf8f52c21a7";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
if (storedDeviceInfo.platform === "web") return;
|
||||||
|
OneSignal.setAppId(onesignal_app_id);
|
||||||
|
const deviceId = await Device.getId();
|
||||||
|
OneSignal.setExternalUserId(deviceId.uuid);
|
||||||
|
/*const res = await fetch(import.meta.env.VITE_NOTIFICATION_TOKEN_ENDPOINT, {
|
||||||
|
method: "POST", // *GET, POST, PUT, DELETE, etc.
|
||||||
|
mode: "cors", // no-cors, *cors, same-origin
|
||||||
|
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
|
||||||
|
credentials: "same-origin", // include, *same-origin, omit
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
redirect: "follow", // manual, *follow, error
|
||||||
|
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
|
||||||
|
body: JSON.stringify({
|
||||||
|
misskey_token: $i.token,
|
||||||
|
device_id: deviceId.uuid,
|
||||||
|
instance_url: $i.instanceUrl,
|
||||||
|
}),
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
// throw err
|
||||||
|
});
|
||||||
|
console.info(res);*/
|
||||||
|
OneSignal.setNotificationOpenedHandler(function (jsonData) {
|
||||||
|
console.log(`notificationOpenedCallback: ${JSON.stringify(jsonData)}`);
|
||||||
|
});
|
||||||
|
// Prompts the user for notification permissions.
|
||||||
|
// * Since this shows a generic native prompt, we recommend instead using an In-App Message to prompt for notification permission (See step 7) to better communicate to your users what notifications they will get.
|
||||||
|
OneSignal.promptForPushNotificationsWithUserResponse(function (accepted) {
|
||||||
|
console.log(`User accepted notifications: ${accepted}`);
|
||||||
|
});
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
// shortcut
|
// shortcut
|
||||||
document.addEventListener("keydown", makeHotkey(hotkeys));
|
document.addEventListener("keydown", makeHotkey(hotkeys));
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
}
|
||||||
|
// #v-else
|
||||||
})();
|
})();
|
||||||
|
// #v-endif
|
||||||
|
|
|
@ -15,7 +15,11 @@ import { $i } from "@/account";
|
||||||
export const pendingApiRequestsCount = ref(0);
|
export const pendingApiRequestsCount = ref(0);
|
||||||
|
|
||||||
const apiClient = new Misskey.api.APIClient({
|
const apiClient = new Misskey.api.APIClient({
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
origin: $i?.instanceUrl || window.location.origin,
|
||||||
|
// #v-else
|
||||||
origin: url,
|
origin: url,
|
||||||
|
// #v-endif
|
||||||
});
|
});
|
||||||
|
|
||||||
export const api = ((
|
export const api = ((
|
||||||
|
|
|
@ -78,6 +78,9 @@ import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
import { deviceKind } from '@/scripts/device-kind';
|
import { deviceKind } from '@/scripts/device-kind';
|
||||||
import 'swiper/scss';
|
import 'swiper/scss';
|
||||||
import 'swiper/scss/virtual';
|
import 'swiper/scss/virtual';
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
import { Camera } from "@capacitor/camera";
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
if (defaultStore.reactiveState.tutorial.value !== -1) {
|
if (defaultStore.reactiveState.tutorial.value !== -1) {
|
||||||
os.popup(XTutorial, {}, {}, 'closed');
|
os.popup(XTutorial, {}, {}, 'closed');
|
||||||
|
@ -339,6 +342,13 @@ onMounted(() => {
|
||||||
syncSlide(timelines.indexOf(swiperRef.activeIndex));
|
syncSlide(timelines.indexOf(swiperRef.activeIndex));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
const permissionState = await Camera.checkPermissions();
|
||||||
|
if (!permissionState.camera) {
|
||||||
|
Camera.requestPermissions({ permissions: ["photos", "camera"] });
|
||||||
|
}
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
<div class="rsqzvsbo">
|
||||||
|
// #v-else
|
||||||
<div v-if="meta" class="rsqzvsbo">
|
<div v-if="meta" class="rsqzvsbo">
|
||||||
|
// #v-endif
|
||||||
<div class="top">
|
<div class="top">
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
<MkFeaturedPhotos class="bg"/>
|
<MkFeaturedPhotos class="bg"/>
|
||||||
<XTimeline class="tl"/>
|
<XTimeline class="tl"/>
|
||||||
|
// #v-endif
|
||||||
<div class="shape1"></div>
|
<div class="shape1"></div>
|
||||||
<div class="shape2"></div>
|
<div class="shape2"></div>
|
||||||
<img src="/client-assets/misskey.svg" class="misskey"/>
|
<img src="/client-assets/misskey.svg" class="misskey"/>
|
||||||
|
@ -20,20 +28,46 @@
|
||||||
<MkEmoji :normal="true" :no-style="true" emoji="🍮"/>
|
<MkEmoji :normal="true" :no-style="true" emoji="🍮"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
<img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/>
|
<img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/>
|
||||||
|
// #v-endif
|
||||||
<button class="_button _acrylic menu" @click="showMenu"><i class="ph-dots-three-outline ph-bold ph-lg"></i></button>
|
<button class="_button _acrylic menu" @click="showMenu"><i class="ph-dots-three-outline ph-bold ph-lg"></i></button>
|
||||||
<div class="fg">
|
<div class="fg">
|
||||||
<h1>
|
<h1>
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
<span class="text">Calckey Mobile</span>
|
||||||
|
// #v-else
|
||||||
<img class="logo" v-if="meta.logoImageUrl" :src="meta.logoImageUrl">
|
<img class="logo" v-if="meta.logoImageUrl" :src="meta.logoImageUrl">
|
||||||
<span v-else class="text">{{ instanceName }}</span>
|
<span v-else class="text">{{ instanceName }}</span>
|
||||||
|
// #v-endif
|
||||||
</h1>
|
</h1>
|
||||||
<div class="about">
|
<div class="about">
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
<div class="desc" v-html="i18n.ts.headlineMisskey"></div>
|
||||||
|
// #v-else
|
||||||
<div class="desc" v-html="meta.description || i18n.ts.headlineMisskey"></div>
|
<div class="desc" v-html="meta.description || i18n.ts.headlineMisskey"></div>
|
||||||
|
// #v-endif
|
||||||
</div>
|
</div>
|
||||||
<div class="action">
|
<div class="action">
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
<div>
|
||||||
|
<input id="term" v-model="isTerm" type="checkbox" /><label
|
||||||
|
for="term"
|
||||||
|
>
|
||||||
|
Agree to Privacy Policy and Terms of Use</label
|
||||||
|
><br />
|
||||||
|
<a href="https://riinswork.space/missRirica/privacy/">
|
||||||
|
Read Privacy Policy and Terms of Use
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<MkButton inline rounded data-cy-signin :disabled="!isTerm" @click="signin()">{{ i18n.ts.login }}</MkButton>
|
||||||
|
// #v-else
|
||||||
<MkButton inline rounded gradate data-cy-signup style="margin-right: 12px;" @click="signup()">{{ i18n.ts.signup }}</MkButton>
|
<MkButton inline rounded gradate data-cy-signup style="margin-right: 12px;" @click="signup()">{{ i18n.ts.signup }}</MkButton>
|
||||||
<MkButton inline rounded data-cy-signin @click="signin()">{{ i18n.ts.login }}</MkButton>
|
<MkButton inline rounded data-cy-signin @click="signin()">{{ i18n.ts.login }}</MkButton>
|
||||||
<MkButton inline rounded style="margin-left: 12px; margin-top: 12px;" onclick="window.location.href='/explore'">Explore</MkButton>
|
<MkButton inline rounded style="margin-left: 12px; margin-top: 12px;" onclick="window.location.href='/explore'">Explore</MkButton>
|
||||||
|
// #v-endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -60,16 +94,23 @@ import MkButton from '@/components/MkButton.vue';
|
||||||
import XNote from '@/components/MkNote.vue';
|
import XNote from '@/components/MkNote.vue';
|
||||||
import MkFeaturedPhotos from '@/components/MkFeaturedPhotos.vue';
|
import MkFeaturedPhotos from '@/components/MkFeaturedPhotos.vue';
|
||||||
import { host, instanceName } from '@/config';
|
import { host, instanceName } from '@/config';
|
||||||
|
import { ref, watch } from "vue";
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import number from '@/filters/number';
|
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import { langs as _langs } from "@/config";
|
||||||
|
|
||||||
|
const langs = ref(_langs);
|
||||||
|
const lang = ref(localStorage.getItem("lang"));
|
||||||
|
|
||||||
|
let isTerm = $ref();
|
||||||
let meta = $ref();
|
let meta = $ref();
|
||||||
let stats = $ref();
|
let stats = $ref();
|
||||||
let tags = $ref();
|
let tags = $ref();
|
||||||
let onlineUsersCount = $ref();
|
let onlineUsersCount = $ref();
|
||||||
let instances = $ref();
|
let instances = $ref();
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
os.api('meta', { detail: true }).then(_meta => {
|
os.api('meta', { detail: true }).then(_meta => {
|
||||||
meta = _meta;
|
meta = _meta;
|
||||||
});
|
});
|
||||||
|
@ -95,19 +136,22 @@ os.api('federation/instances', {
|
||||||
}).then(_instances => {
|
}).then(_instances => {
|
||||||
instances = _instances;
|
instances = _instances;
|
||||||
});
|
});
|
||||||
|
// #v-endif
|
||||||
function signin() {
|
function signin() {
|
||||||
os.popup(XSigninDialog, {
|
os.popup(XSigninDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {}, 'closed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
function signup() {
|
function signup() {
|
||||||
os.popup(XSignupDialog, {
|
os.popup(XSignupDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {}, 'closed');
|
||||||
}
|
}
|
||||||
|
// #v-endif
|
||||||
function showMenu(ev) {
|
function showMenu(ev) {
|
||||||
os.popupMenu([{
|
os.popupMenu([{
|
||||||
text: i18n.ts.instanceInfo,
|
text: i18n.ts.instanceInfo,
|
||||||
|
@ -123,6 +167,34 @@ function showMenu(ev) {
|
||||||
},
|
},
|
||||||
}], ev.currentTarget ?? ev.target);
|
}], ev.currentTarget ?? ev.target);
|
||||||
}
|
}
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
watch(lang, () => {
|
||||||
|
localStorage.setItem("lang", lang.value as string);
|
||||||
|
localStorage.removeItem("locale");
|
||||||
|
});
|
||||||
|
|
||||||
|
watch([lang], async () => {
|
||||||
|
await reloadAsk();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function reloadAsk() {
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
|
type: "info",
|
||||||
|
text: i18n.ts.reloadToApplySetting,
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
unisonReload();
|
||||||
|
}
|
||||||
|
|
||||||
|
function unisonReload(path?: string) {
|
||||||
|
if (path !== undefined) {
|
||||||
|
location.href = path;
|
||||||
|
} else {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #v-endif
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -73,7 +73,11 @@ export default defineComponent({
|
||||||
MkButton,
|
MkButton,
|
||||||
XNote,
|
XNote,
|
||||||
MkFeaturedPhotos,
|
MkFeaturedPhotos,
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
XTimeline,
|
XTimeline,
|
||||||
|
// #v-endif
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
<XEntrance />
|
||||||
|
// #v-else
|
||||||
<div v-if="meta">
|
<div v-if="meta">
|
||||||
<XSetup v-if="meta.requireSetup"/>
|
<XSetup v-if="meta.requireSetup"/>
|
||||||
<XEntrance v-else/>
|
<XEntrance v-else/>
|
||||||
</div>
|
</div>
|
||||||
|
// #v-endif
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import XEntrance from './welcome.entrance.a.vue';
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
//...
|
||||||
|
// #v-else
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import XSetup from './welcome.setup.vue';
|
import XSetup from './welcome.setup.vue';
|
||||||
import XEntrance from './welcome.entrance.a.vue';
|
|
||||||
import { instanceName } from '@/config';
|
import { instanceName } from '@/config';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
|
@ -27,4 +34,5 @@ definePageMetadata(computed(() => ({
|
||||||
title: instanceName,
|
title: instanceName,
|
||||||
icon: null,
|
icon: null,
|
||||||
})));
|
})));
|
||||||
|
// #v-endif
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -15,6 +15,9 @@ import lightTheme from "@/themes/_light.json5";
|
||||||
import darkTheme from "@/themes/_dark.json5";
|
import darkTheme from "@/themes/_dark.json5";
|
||||||
import { deepClone } from "./clone";
|
import { deepClone } from "./clone";
|
||||||
|
|
||||||
|
import { StatusBar, Style } from "@capacitor/status-bar";
|
||||||
|
import { storedDeviceInfo } from "@/init";
|
||||||
|
|
||||||
export const themeProps = Object.keys(lightTheme.props).filter(
|
export const themeProps = Object.keys(lightTheme.props).filter(
|
||||||
(key) => !key.startsWith("X"),
|
(key) => !key.startsWith("X"),
|
||||||
);
|
);
|
||||||
|
@ -140,6 +143,13 @@ function compile(theme: Theme): Record<string, string> {
|
||||||
return color.saturate(arg);
|
return color.saturate(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
if (storedDeviceInfo.platform === "ios") {
|
||||||
|
StatusBar.setStyle({
|
||||||
|
style: theme.base === "dark" ? Style.Dark : Style.Light,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// #v-endif
|
||||||
|
|
||||||
// other case
|
// other case
|
||||||
return tinycolor(val);
|
return tinycolor(val);
|
||||||
|
|
|
@ -5,7 +5,11 @@ import { url } from "@/config";
|
||||||
|
|
||||||
export const stream = markRaw(
|
export const stream = markRaw(
|
||||||
new Misskey.Stream(
|
new Misskey.Stream(
|
||||||
|
// #v-ifdef VITE_CAPACITOR
|
||||||
|
$i? $i.instanceUrl : "localhost",
|
||||||
|
// #v-else
|
||||||
url,
|
url,
|
||||||
|
// #v-endif
|
||||||
$i
|
$i
|
||||||
? {
|
? {
|
||||||
token: $i.token,
|
token: $i.token,
|
||||||
|
|
|
@ -81,7 +81,6 @@ const isTimelineAvailable = !instance.disableLocalTimeline || !instance.disableR
|
||||||
let showMenu = $ref(false);
|
let showMenu = $ref(false);
|
||||||
let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
||||||
let narrow = $ref(window.innerWidth < 1280);
|
let narrow = $ref(window.innerWidth < 1280);
|
||||||
let meta = $ref();
|
|
||||||
|
|
||||||
const keymap = $computed(() => {
|
const keymap = $computed(() => {
|
||||||
return {
|
return {
|
||||||
|
@ -95,10 +94,6 @@ const keymap = $computed(() => {
|
||||||
|
|
||||||
const root = $computed(() => mainRouter.currentRoute.value.name === 'index');
|
const root = $computed(() => mainRouter.currentRoute.value.name === 'index');
|
||||||
|
|
||||||
os.api('meta', { detail: true }).then(res => {
|
|
||||||
meta = res;
|
|
||||||
});
|
|
||||||
|
|
||||||
function signin() {
|
function signin() {
|
||||||
os.popup(XSigninDialog, {
|
os.popup(XSigninDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
|
|
|
@ -598,6 +598,9 @@ importers:
|
||||||
'@capacitor/app':
|
'@capacitor/app':
|
||||||
specifier: ^4.1.1
|
specifier: ^4.1.1
|
||||||
version: 4.1.1(@capacitor/core@4.7.3)
|
version: 4.1.1(@capacitor/core@4.7.3)
|
||||||
|
'@capacitor/camera':
|
||||||
|
specifier: ^4.1.4
|
||||||
|
version: 4.1.4(@capacitor/core@4.7.3)
|
||||||
'@capacitor/core':
|
'@capacitor/core':
|
||||||
specifier: ^4.7.3
|
specifier: ^4.7.3
|
||||||
version: 4.7.3
|
version: 4.7.3
|
||||||
|
@ -1119,6 +1122,14 @@ packages:
|
||||||
'@capacitor/core': 4.7.3
|
'@capacitor/core': 4.7.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@capacitor/camera@4.1.4(@capacitor/core@4.7.3):
|
||||||
|
resolution: {integrity: sha512-7f4n7PlnstYsdGyxc0Kc4hIyS6csFLOjXvffm7pJsuy9pSo+kfdOPdYgGg360QwbUAmA+Yv+J1ZW1eFIwgvWrQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@capacitor/core': ^4.0.0
|
||||||
|
dependencies:
|
||||||
|
'@capacitor/core': 4.7.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@capacitor/cli@4.7.3:
|
/@capacitor/cli@4.7.3:
|
||||||
resolution: {integrity: sha512-/9Vjl0A91UjRA0b8a5YCqHfHcM50vQ3Fh0typ3ScwYZhg3shkFtB03e8liAD/u0rhr/MerN8VGgN75QNEXN0Lg==}
|
resolution: {integrity: sha512-/9Vjl0A91UjRA0b8a5YCqHfHcM50vQ3Fh0typ3ScwYZhg3shkFtB03e8liAD/u0rhr/MerN8VGgN75QNEXN0Lg==}
|
||||||
engines: {node: '>=12.4.0'}
|
engines: {node: '>=12.4.0'}
|
||||||
|
|
Loading…
Reference in New Issue