Frontend: Prettier loading icons
ci/woodpecker/push/ociImagePush Pipeline was successful
Details
ci/woodpecker/push/ociImagePush Pipeline was successful
Details
This commit is contained in:
parent
6c7e3d79e0
commit
7c44e55597
|
@ -1,14 +1,15 @@
|
||||||
use async_stream::stream;
|
use async_stream::stream;
|
||||||
use futures_util::{select, stream::StreamExt, FutureExt, Stream, TryStreamExt};
|
use futures_util::{FutureExt, select, Stream, stream::StreamExt, TryStreamExt};
|
||||||
use headers::UserAgent;
|
use headers::UserAgent;
|
||||||
use hyper::body::Bytes;
|
use hyper::body::Bytes;
|
||||||
use magnetar_core::web_model::ContentType;
|
use reqwest::{Client, redirect::Policy, RequestBuilder};
|
||||||
use reqwest::{redirect::Policy, Client, RequestBuilder};
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::pin;
|
use tokio::pin;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use magnetar_core::web_model::ContentType;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FederationClient {
|
pub struct FederationClient {
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
|
@ -118,8 +119,10 @@ impl FederationRequestBuilder<'_> {
|
||||||
|
|
||||||
async fn send_stream(
|
async fn send_stream(
|
||||||
self,
|
self,
|
||||||
) -> Result<impl Stream<Item = Result<Bytes, FederationClientError>>, FederationClientError>
|
) -> Result<impl Stream<Item=Result<Bytes, FederationClientError>>, FederationClientError>
|
||||||
{
|
{
|
||||||
|
eprintln!("{:?}", self.builder);
|
||||||
|
|
||||||
let mut body = self
|
let mut body = self
|
||||||
.builder
|
.builder
|
||||||
.send()
|
.send()
|
||||||
|
@ -146,7 +149,7 @@ impl FederationRequestBuilder<'_> {
|
||||||
let sleep = tokio::time::sleep(tokio::time::Duration::from_secs(
|
let sleep = tokio::time::sleep(tokio::time::Duration::from_secs(
|
||||||
self.client.timeout_seconds,
|
self.client.timeout_seconds,
|
||||||
))
|
))
|
||||||
.fuse();
|
.fuse();
|
||||||
tokio::pin!(sleep);
|
tokio::pin!(sleep);
|
||||||
|
|
||||||
let body = async move {
|
let body = async move {
|
||||||
|
@ -158,7 +161,7 @@ impl FederationRequestBuilder<'_> {
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
.fuse();
|
.fuse();
|
||||||
|
|
||||||
pin!(body);
|
pin!(body);
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
:pinned="pinned"
|
:pinned="pinned"
|
||||||
>
|
>
|
||||||
</XNote>
|
</XNote>
|
||||||
<div v-else>
|
<div class="spinner-container" v-else>
|
||||||
<i class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"></i>
|
<MagSpinner />
|
||||||
|
Fetching
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -39,6 +40,17 @@ watch(
|
||||||
noteData.value = n;
|
noteData.value = n;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.spinner-container {
|
||||||
|
margin: 12px 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.2em;
|
||||||
|
gap: 0.4em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -47,10 +47,7 @@
|
||||||
<a v-if="!pollRefreshing" @click.stop="refresh">{{
|
<a v-if="!pollRefreshing" @click.stop="refresh">{{
|
||||||
i18n.ts.reload
|
i18n.ts.reload
|
||||||
}}</a>
|
}}</a>
|
||||||
<i
|
<MagSpinner v-else />
|
||||||
v-else
|
|
||||||
class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"
|
|
||||||
></i>
|
|
||||||
</span>
|
</span>
|
||||||
<span v-if="isVoted"> · {{ i18n.ts._poll.voted }}</span>
|
<span v-if="isVoted"> · {{ i18n.ts._poll.voted }}</span>
|
||||||
<span v-else-if="closed"> · {{ i18n.ts._poll.closed }}</span>
|
<span v-else-if="closed"> · {{ i18n.ts._poll.closed }}</span>
|
||||||
|
@ -77,31 +74,31 @@ const pollRefreshing = ref(false);
|
||||||
const remaining = ref(-1);
|
const remaining = ref(-1);
|
||||||
|
|
||||||
const total = computed(() =>
|
const total = computed(() =>
|
||||||
sum(props.note.poll.options.map((x) => x.votes_count)),
|
sum(props.note.poll.options.map((x) => x.votes_count))
|
||||||
);
|
);
|
||||||
const closed = computed(() => remaining.value === 0);
|
const closed = computed(() => remaining.value === 0);
|
||||||
const isLocal = computed(() => !props.note.uri);
|
const isLocal = computed(() => !props.note.uri);
|
||||||
const isVoted = computed(
|
const isVoted = computed(
|
||||||
() =>
|
() =>
|
||||||
!props.note.poll.multiple_choice &&
|
!props.note.poll.multiple_choice &&
|
||||||
props.note.poll.options.some((c) => c.voted ?? false),
|
props.note.poll.options.some((c) => c.voted ?? false)
|
||||||
);
|
);
|
||||||
const timer = computed(() =>
|
const timer = computed(() =>
|
||||||
i18n.t(
|
i18n.t(
|
||||||
remaining.value >= 86400
|
remaining.value >= 86400
|
||||||
? "_poll.remainingDays"
|
? "_poll.remainingDays"
|
||||||
: remaining.value >= 3600
|
: remaining.value >= 3600
|
||||||
? "_poll.remainingHours"
|
? "_poll.remainingHours"
|
||||||
: remaining.value >= 60
|
: remaining.value >= 60
|
||||||
? "_poll.remainingMinutes"
|
? "_poll.remainingMinutes"
|
||||||
: "_poll.remainingSeconds",
|
: "_poll.remainingSeconds",
|
||||||
{
|
{
|
||||||
s: Math.floor(remaining.value % 60),
|
s: Math.floor(remaining.value % 60),
|
||||||
m: Math.floor(remaining.value / 60) % 60,
|
m: Math.floor(remaining.value / 60) % 60,
|
||||||
h: Math.floor(remaining.value / 3600) % 24,
|
h: Math.floor(remaining.value / 3600) % 24,
|
||||||
d: Math.floor(remaining.value / 86400),
|
d: Math.floor(remaining.value / 86400),
|
||||||
},
|
}
|
||||||
),
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const showResult = ref(props.readOnly || isVoted.value);
|
const showResult = ref(props.readOnly || isVoted.value);
|
||||||
|
@ -112,8 +109,8 @@ if (props.note.poll.expires_at) {
|
||||||
remaining.value = Math.floor(
|
remaining.value = Math.floor(
|
||||||
Math.max(
|
Math.max(
|
||||||
new Date(props.note.poll.expires_at!).getTime() - Date.now(),
|
new Date(props.note.poll.expires_at!).getTime() - Date.now(),
|
||||||
0,
|
0
|
||||||
) / 1000,
|
) / 1000
|
||||||
);
|
);
|
||||||
if (remaining.value === 0) {
|
if (remaining.value === 0) {
|
||||||
showResult.value = true;
|
showResult.value = true;
|
||||||
|
@ -137,7 +134,7 @@ async function refresh() {
|
||||||
os.magApi(
|
os.magApi(
|
||||||
endpoints.GetNoteById,
|
endpoints.GetNoteById,
|
||||||
{ attachments: true },
|
{ attachments: true },
|
||||||
{ id: obj.object.id },
|
{ id: obj.object.id }
|
||||||
).then((n) => {
|
).then((n) => {
|
||||||
props.note.poll = { ...toRaw(props.note.poll), ...n.poll };
|
props.note.poll = { ...toRaw(props.note.poll), ...n.poll };
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<template v-if="waitIncoming">
|
<template v-if="waitIncoming">
|
||||||
<i class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"></i>
|
<MagSpinner />
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
>
|
>
|
||||||
<!-- つまりリモートフォローの場合。 -->
|
<!-- つまりリモートフォローの場合。 -->
|
||||||
<span>{{ (state = i18n.ts.processing) }}</span
|
<span>{{ (state = i18n.ts.processing) }}</span
|
||||||
><i class="ph-circle-notch ph-bold ph-lg fa-pulse"></i>
|
><MagSpinner />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="isFollowing">
|
<template v-else-if="isFollowing">
|
||||||
<span>{{ (state = i18n.ts.unfollow) }}</span
|
<span>{{ (state = i18n.ts.unfollow) }}</span
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span>{{ (state = i18n.ts.processing) }}</span
|
<span>{{ (state = i18n.ts.processing) }}</span
|
||||||
><i class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"></i>
|
><MagSpinner />
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -52,7 +52,6 @@ const props = withDefaults(
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
let hide = ref(true);
|
let hide = ref(true);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -101,6 +100,7 @@ let hide = ref(true);
|
||||||
& fieldset.audio-player-frame {
|
& fieldset.audio-player-frame {
|
||||||
border-color: var(--accentedBg);
|
border-color: var(--accentedBg);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
border-style: solid;
|
||||||
|
|
||||||
& legend {
|
& legend {
|
||||||
padding-inline: 5px;
|
padding-inline: 5px;
|
||||||
|
|
|
@ -47,15 +47,17 @@
|
||||||
v-tooltip:dialog="i18n.ts.usernameInfo"
|
v-tooltip:dialog="i18n.ts.usernameInfo"
|
||||||
class="_button _help"
|
class="_button _help"
|
||||||
>
|
>
|
||||||
<i class="ph-question ph-bold"></i></div
|
<i class="ph-question ph-bold"></i>
|
||||||
></template>
|
</div>
|
||||||
|
</template>
|
||||||
<template #prefix>@</template>
|
<template #prefix>@</template>
|
||||||
<template #suffix>@{{ host }}</template>
|
<template #suffix>@{{ host }}</template>
|
||||||
<template #caption>
|
<template #caption>
|
||||||
<span v-if="usernameState === 'wait'" style="color: #6e6a86"
|
<span
|
||||||
><i
|
v-if="usernameState === 'wait'"
|
||||||
class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"
|
style="color: #6e6a86"
|
||||||
></i>
|
>
|
||||||
|
<MagSpinner />
|
||||||
{{ i18n.ts.checking }}</span
|
{{ i18n.ts.checking }}</span
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
@ -113,16 +115,15 @@
|
||||||
v-tooltip:dialog="i18n.ts._signup.emailAddressInfo"
|
v-tooltip:dialog="i18n.ts._signup.emailAddressInfo"
|
||||||
class="_button _help"
|
class="_button _help"
|
||||||
>
|
>
|
||||||
<i class="ph-question ph-bold"></i></div
|
<i class="ph-question ph-bold"></i>
|
||||||
></template>
|
</div>
|
||||||
|
</template>
|
||||||
<template #prefix
|
<template #prefix
|
||||||
><i class="ph-envelope-simple-open ph-bold ph-lg"></i
|
><i class="ph-envelope-simple-open ph-bold ph-lg"></i
|
||||||
></template>
|
></template>
|
||||||
<template #caption>
|
<template #caption>
|
||||||
<span v-if="emailState === 'wait'" style="color: #6e6a86"
|
<span v-if="emailState === 'wait'" style="color: #6e6a86">
|
||||||
><i
|
<MagSpinner />
|
||||||
class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"
|
|
||||||
></i>
|
|
||||||
{{ i18n.ts.checking }}</span
|
{{ i18n.ts.checking }}</span
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
@ -219,8 +220,8 @@
|
||||||
@update:modelValue="onChangePasswordRetype"
|
@update:modelValue="onChangePasswordRetype"
|
||||||
>
|
>
|
||||||
<template #label
|
<template #label
|
||||||
>{{ i18n.ts.password }} ({{ i18n.ts.retype }})</template
|
>{{ i18n.ts.password }} ({{ i18n.ts.retype }})
|
||||||
>
|
</template>
|
||||||
<template #prefix
|
<template #prefix
|
||||||
><i class="ph-lock ph-bold ph-lg"></i
|
><i class="ph-lock ph-bold ph-lg"></i
|
||||||
></template>
|
></template>
|
||||||
|
@ -277,16 +278,14 @@
|
||||||
:disabled="shouldDisableSubmitting"
|
:disabled="shouldDisableSubmitting"
|
||||||
gradate
|
gradate
|
||||||
data-cy-signup-submit
|
data-cy-signup-submit
|
||||||
>{{ i18n.ts.start }}</MkButton
|
>{{ i18n.ts.start }}
|
||||||
>
|
</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from "vue";
|
import { computed, ref } from "vue";
|
||||||
|
|
||||||
import {} from "vue";
|
|
||||||
import getPasswordStrength from "syuilo-password-strength";
|
import getPasswordStrength from "syuilo-password-strength";
|
||||||
import { toUnicode } from "punycode/";
|
import { toUnicode } from "punycode/";
|
||||||
import MkButton from "./MkButton.vue";
|
import MkButton from "./MkButton.vue";
|
||||||
|
@ -305,7 +304,7 @@ const props = withDefaults(
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
autoSet: false,
|
autoSet: false,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -379,10 +378,10 @@ function onChangeUsername(): void {
|
||||||
const err = !username.value.match(/^[a-zA-Z0-9_]+$/)
|
const err = !username.value.match(/^[a-zA-Z0-9_]+$/)
|
||||||
? "invalid-format"
|
? "invalid-format"
|
||||||
: username.value.length < 1
|
: username.value.length < 1
|
||||||
? "min-range"
|
? "min-range"
|
||||||
: username.value.length > 20
|
: username.value.length > 20
|
||||||
? "max-range"
|
? "max-range"
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
usernameState.value = err;
|
usernameState.value = err;
|
||||||
|
@ -418,16 +417,16 @@ function onChangeEmail(): void {
|
||||||
emailState.value = result.available
|
emailState.value = result.available
|
||||||
? "ok"
|
? "ok"
|
||||||
: result.reason === "used"
|
: result.reason === "used"
|
||||||
? "unavailable:used"
|
? "unavailable:used"
|
||||||
: result.reason === "format"
|
: result.reason === "format"
|
||||||
? "unavailable:format"
|
? "unavailable:format"
|
||||||
: result.reason === "disposable"
|
: result.reason === "disposable"
|
||||||
? "unavailable:disposable"
|
? "unavailable:disposable"
|
||||||
: result.reason === "mx"
|
: result.reason === "mx"
|
||||||
? "unavailable:mx"
|
? "unavailable:mx"
|
||||||
: result.reason === "smtp"
|
: result.reason === "smtp"
|
||||||
? "unavailable:smtp"
|
? "unavailable:smtp"
|
||||||
: "unavailable";
|
: "unavailable";
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
emailState.value = "error";
|
emailState.value = "error";
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
<template>
|
||||||
|
<i class="simple ph-hourglass ph-bold ph-lg" :aria-label="i18n.ts.busy"></i>
|
||||||
|
<svg
|
||||||
|
class="animated mag-spinner"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 67.733 67.733"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<g class="mag-ring" transform="matrix(.82287 0 0 .82287 5.9984 5.9989)">
|
||||||
|
<path
|
||||||
|
d="m33.959 0.8413c-8.3737-0.008823-16.592 3.1643-22.849 9.1188-8.8995 8.4685-12.376 21.177-9.023 32.996l5.9686-1.681c-2.7249-9.6065 0.095231-19.927 7.329-26.811 7.2337-6.8834 17.845-8.9517 26.103-6.264l1.9737-5.9045c-2.9094-0.98361-4.8438-1.2553-7.8257-1.41-0.55911-0.028992-1.1178-0.044097-1.676-0.04468zm31.826 24.715-6.0201 1.553c2.4674 9.2417-0.15852 19.094-6.8993 25.88-6.7409 6.7861-16.177 9.1968-25.564 6.8428l-1.6444 5.9555c11.39 2.9597 23.3-0.07129 31.594-8.4205 8.2936-8.3492 11.569-20.441 8.5336-31.811z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
class="mag-butterflies"
|
||||||
|
transform="matrix(1.2958 .098299 -.098299 1.2958 .41715 -18.811)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m19.244 39.965c-0.62132 0.75445-1.2862 1.4845-1.8805 2.2541-0.45826 1.4275-0.95911 2.8484-1.3908 4.28 0.01197 0.7973 0.02382 1.5946 0.03574 2.3919-0.82611-0.0559-1.656-0.15529-2.4798-0.18435-1.4482 0.38557-2.9176 0.72632-4.3525 1.1398-0.76206 0.56257-1.5241 1.1251-2.2862 1.6877 0.00746 0.57752 0.014929 1.155 0.022392 1.7326 0.85814 0.49688 1.6647 1.0953 2.6101 1.4204 0.76646 0.32006 1.5329 0.64012 2.2994 0.96018 0.53911-0.39567 1.0782-0.79134 1.6173-1.187 0.01331 0.4126 0.02652 0.82522 0.03983 1.2378 0.55847 0.37816 1.0935 0.81873 1.6666 1.1579 0.94848 0.09538 1.897 0.19074 2.8454 0.28611 0.79636-0.46986 1.5927-0.93971 2.3891-1.4096-0.14459-0.67269-0.24382-1.3636-0.41647-2.025-0.40398-0.62711-0.79926-1.2606-1.2086-1.8838 0.62691 0.4569 1.2427 0.94576 1.8866 1.3706 0.63581 0.16906 1.2716 0.33814 1.9074 0.5072 0.52106-0.76381 1.0421-1.5276 1.5632-2.2914-0.05014-0.9802-0.03649-1.9797-0.12641-2.9479-0.33964-0.54964-0.67928-1.0993-1.0189-1.6489-0.41083-0.04035-0.82165-0.08069-1.2325-0.12099 0.43013-0.51202 0.86026-1.024 1.2904-1.5361-0.39788-1.1174-0.74239-2.2576-1.1736-3.3607-0.29327-0.56483-0.58654-1.1297-0.8798-1.6945-0.5758-0.0454-1.1516-0.09072-1.7274-0.13608z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
class="mag-butterflies"
|
||||||
|
transform="matrix(-1.2957 -.098293 .098293 -1.2957 66.781 86.854)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m19.244 39.965c-0.62132 0.75445-1.2862 1.4845-1.8805 2.2541-0.45826 1.4275-0.95911 2.8484-1.3908 4.28 0.01197 0.7973 0.02382 1.5946 0.03574 2.3919-0.82611-0.0559-1.656-0.15529-2.4798-0.18435-1.4482 0.38557-2.9176 0.72632-4.3525 1.1398-0.76206 0.56257-1.5241 1.1251-2.2862 1.6877 0.00746 0.57752 0.014929 1.155 0.022392 1.7326 0.85814 0.49688 1.6647 1.0953 2.6101 1.4204 0.76646 0.32006 1.5329 0.64012 2.2994 0.96018 0.53911-0.39567 1.0782-0.79134 1.6173-1.187 0.01331 0.4126 0.02652 0.82522 0.03983 1.2378 0.55847 0.37816 1.0935 0.81873 1.6666 1.1579 0.94848 0.09538 1.897 0.19074 2.8454 0.28611 0.79636-0.46986 1.5927-0.93971 2.3891-1.4096-0.14459-0.67269-0.24382-1.3636-0.41647-2.025-0.40398-0.62711-0.79926-1.2606-1.2086-1.8838 0.62691 0.4569 1.2427 0.94576 1.8866 1.3706 0.63581 0.16906 1.2716 0.33814 1.9074 0.5072 0.52106-0.76381 1.0421-1.5276 1.5632-2.2914-0.05014-0.9802-0.03649-1.9797-0.12641-2.9479-0.33964-0.54964-0.67928-1.0993-1.0189-1.6489-0.41083-0.04035-0.82165-0.08069-1.2325-0.12099 0.43013-0.51202 0.86026-1.024 1.2904-1.5361-0.39788-1.1174-0.74239-2.2576-1.1736-3.3607-0.29327-0.56483-0.58654-1.1297-0.8798-1.6945-0.5758-0.0454-1.1516-0.09072-1.7274-0.13608z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { i18n } from "@/i18n";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.simple {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mag-spinner.animated {
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
transform-origin: center;
|
||||||
|
animation-name: mag-ring-rotate;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-direction: normal;
|
||||||
|
animation-duration: 3s;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes mag-ring-rotate {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion) {
|
||||||
|
.simple {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animated {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,37 +1,50 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
:class="[
|
:class="[
|
||||||
$style.root,
|
$style['mag-spinner-loading'],
|
||||||
{
|
{
|
||||||
[$style.inline]: inline,
|
[$style.inline]: inline,
|
||||||
[$style.colored]: colored,
|
[$style.colored]: colored,
|
||||||
[$style.mini]: mini,
|
[$style.mini]: mini,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 67.733 67.733"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<div :class="$style.container" aria-hidden="true">
|
<g :class="$style['mag-spinner-spin']">
|
||||||
<svg
|
<g transform="matrix(.82287 0 0 .82287 5.9984 5.9989)">
|
||||||
:class="[$style.spinner]"
|
<path
|
||||||
viewBox="0 0 50 50"
|
d="m33.959 0.8413c-8.3737-0.008823-16.592 3.1643-22.849 9.1188-8.8995 8.4685-12.376 21.177-9.023 32.996l5.9686-1.681c-2.7249-9.6065 0.095231-19.927 7.329-26.811 7.2337-6.8834 17.845-8.9517 26.103-6.264l1.9737-5.9045c-2.9094-0.98361-4.8438-1.2553-7.8257-1.41-0.55911-0.028992-1.1178-0.044097-1.676-0.04468zm31.826 24.715-6.0201 1.553c2.4674 9.2417-0.15852 19.094-6.8993 25.88-6.7409 6.7861-16.177 9.1968-25.564 6.8428l-1.6444 5.9555c11.39 2.9597 23.3-0.07129 31.594-8.4205 8.2936-8.3492 11.569-20.441 8.5336-31.811z"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
:class="$style['mag-butterflies']"
|
||||||
|
transform="matrix(1.2958 .098299 -.098299 1.2958 .41715 -18.811)"
|
||||||
>
|
>
|
||||||
<circle
|
<path
|
||||||
:class="[$style.path]"
|
d="m19.244 39.965c-0.62132 0.75445-1.2862 1.4845-1.8805 2.2541-0.45826 1.4275-0.95911 2.8484-1.3908 4.28 0.01197 0.7973 0.02382 1.5946 0.03574 2.3919-0.82611-0.0559-1.656-0.15529-2.4798-0.18435-1.4482 0.38557-2.9176 0.72632-4.3525 1.1398-0.76206 0.56257-1.5241 1.1251-2.2862 1.6877 0.00746 0.57752 0.014929 1.155 0.022392 1.7326 0.85814 0.49688 1.6647 1.0953 2.6101 1.4204 0.76646 0.32006 1.5329 0.64012 2.2994 0.96018 0.53911-0.39567 1.0782-0.79134 1.6173-1.187 0.01331 0.4126 0.02652 0.82522 0.03983 1.2378 0.55847 0.37816 1.0935 0.81873 1.6666 1.1579 0.94848 0.09538 1.897 0.19074 2.8454 0.28611 0.79636-0.46986 1.5927-0.93971 2.3891-1.4096-0.14459-0.67269-0.24382-1.3636-0.41647-2.025-0.40398-0.62711-0.79926-1.2606-1.2086-1.8838 0.62691 0.4569 1.2427 0.94576 1.8866 1.3706 0.63581 0.16906 1.2716 0.33814 1.9074 0.5072 0.52106-0.76381 1.0421-1.5276 1.5632-2.2914-0.05014-0.9802-0.03649-1.9797-0.12641-2.9479-0.33964-0.54964-0.67928-1.0993-1.0189-1.6489-0.41083-0.04035-0.82165-0.08069-1.2325-0.12099 0.43013-0.51202 0.86026-1.024 1.2904-1.5361-0.39788-1.1174-0.74239-2.2576-1.1736-3.3607-0.29327-0.56483-0.58654-1.1297-0.8798-1.6945-0.5758-0.0454-1.1516-0.09072-1.7274-0.13608z"
|
||||||
cx="25"
|
fill="currentColor"
|
||||||
cy="25"
|
/>
|
||||||
r="20"
|
</g>
|
||||||
fill="none"
|
<g
|
||||||
stroke-width="6px"
|
:class="$style['mag-butterflies']"
|
||||||
style="fill: none; stroke: currentColor; stroke-width: 6px"
|
transform="matrix(-1.2957 -.098293 .098293 -1.2957 66.781 86.854)"
|
||||||
></circle>
|
>
|
||||||
</svg>
|
<path
|
||||||
</div>
|
d="m19.244 39.965c-0.62132 0.75445-1.2862 1.4845-1.8805 2.2541-0.45826 1.4275-0.95911 2.8484-1.3908 4.28 0.01197 0.7973 0.02382 1.5946 0.03574 2.3919-0.82611-0.0559-1.656-0.15529-2.4798-0.18435-1.4482 0.38557-2.9176 0.72632-4.3525 1.1398-0.76206 0.56257-1.5241 1.1251-2.2862 1.6877 0.00746 0.57752 0.014929 1.155 0.022392 1.7326 0.85814 0.49688 1.6647 1.0953 2.6101 1.4204 0.76646 0.32006 1.5329 0.64012 2.2994 0.96018 0.53911-0.39567 1.0782-0.79134 1.6173-1.187 0.01331 0.4126 0.02652 0.82522 0.03983 1.2378 0.55847 0.37816 1.0935 0.81873 1.6666 1.1579 0.94848 0.09538 1.897 0.19074 2.8454 0.28611 0.79636-0.46986 1.5927-0.93971 2.3891-1.4096-0.14459-0.67269-0.24382-1.3636-0.41647-2.025-0.40398-0.62711-0.79926-1.2606-1.2086-1.8838 0.62691 0.4569 1.2427 0.94576 1.8866 1.3706 0.63581 0.16906 1.2716 0.33814 1.9074 0.5072 0.52106-0.76381 1.0421-1.5276 1.5632-2.2914-0.05014-0.9802-0.03649-1.9797-0.12641-2.9479-0.33964-0.54964-0.67928-1.0993-1.0189-1.6489-0.41083-0.04035-0.82165-0.08069-1.2325-0.12099 0.43013-0.51202 0.86026-1.024 1.2904-1.5361-0.39788-1.1174-0.74239-2.2576-1.1736-3.3607-0.29327-0.56483-0.58654-1.1297-0.8798-1.6945-0.5758-0.0454-1.1516-0.09072-1.7274-0.13608z"
|
||||||
</div>
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {} from "vue";
|
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
inline?: boolean;
|
inline?: boolean;
|
||||||
|
@ -44,14 +57,12 @@ const props = withDefaults(
|
||||||
colored: true,
|
colored: true,
|
||||||
mini: false,
|
mini: false,
|
||||||
em: false,
|
em: false,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
/* Credit to https://codepen.io/supah/pen/BjYLdW */
|
@keyframes mag-loading-spin {
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
0% {
|
0% {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
}
|
}
|
||||||
|
@ -60,25 +71,33 @@ const props = withDefaults(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes dash {
|
@keyframes mag-loading-butterfly-appear {
|
||||||
0% {
|
0% {
|
||||||
stroke-dasharray: 1, 150;
|
opacity: 0;
|
||||||
stroke-dashoffset: 0;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
stroke-dasharray: 90, 150;
|
|
||||||
stroke-dashoffset: -35;
|
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
stroke-dasharray: 90, 150;
|
opacity: 1;
|
||||||
stroke-dashoffset: -124;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.root {
|
.mag-butterflies {
|
||||||
padding: 32px;
|
opacity: 0;
|
||||||
text-align: center;
|
animation: 1s mag-loading-butterfly-appear 0s 1 ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mag-spinner-spin {
|
||||||
|
animation: 2.5s mag-loading-spin infinite linear;
|
||||||
|
transform-origin: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mag-spinner-loading {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
margin-block: 32px;
|
||||||
cursor: wait;
|
cursor: wait;
|
||||||
|
width: var(--size);
|
||||||
|
height: var(--size);
|
||||||
|
|
||||||
--size: 40px;
|
--size: 40px;
|
||||||
|
|
||||||
|
@ -88,42 +107,22 @@ const props = withDefaults(
|
||||||
|
|
||||||
&.inline {
|
&.inline {
|
||||||
display: inline;
|
display: inline;
|
||||||
padding: 0;
|
|
||||||
--size: 32px;
|
--size: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mini {
|
&.mini {
|
||||||
padding: 16px;
|
margin: 16px;
|
||||||
--size: 32px;
|
--size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(.inline) {
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
&.em {
|
&.em {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
padding: 0;
|
|
||||||
--size: 1em;
|
--size: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
|
||||||
position: relative;
|
|
||||||
width: var(--size);
|
|
||||||
height: var(--size);
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 999;
|
|
||||||
width: var(--size);
|
|
||||||
height: var(--size);
|
|
||||||
animation: spin 2s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.path {
|
|
||||||
stroke: var(--accent);
|
|
||||||
stroke-linecap: round;
|
|
||||||
animation: dash 1.2s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -60,12 +60,14 @@ import MkError from "./components/global/MkError.vue";
|
||||||
import MkPageHeader from "./components/global/MkPageHeader.vue";
|
import MkPageHeader from "./components/global/MkPageHeader.vue";
|
||||||
import MkSpacer from "./components/global/MkSpacer.vue";
|
import MkSpacer from "./components/global/MkSpacer.vue";
|
||||||
import MkStickyContainer from "./components/global/MkStickyContainer.vue";
|
import MkStickyContainer from "./components/global/MkStickyContainer.vue";
|
||||||
|
import MagSpinner from "@/components/global/MagSpinner.vue";
|
||||||
|
|
||||||
function globalComponents(app: App) {
|
function globalComponents(app: App) {
|
||||||
app.component("I18n", I18n);
|
app.component("I18n", I18n);
|
||||||
app.component("RouterView", RouterView);
|
app.component("RouterView", RouterView);
|
||||||
app.component("Mfm", Mfm);
|
app.component("Mfm", Mfm);
|
||||||
app.component("MkA", MkA);
|
app.component("MkA", MkA);
|
||||||
|
app.component("MagSpinner", MagSpinner);
|
||||||
app.component("MkAcct", MkAcct);
|
app.component("MkAcct", MkAcct);
|
||||||
app.component("MagAvatar", MagAvatar);
|
app.component("MagAvatar", MagAvatar);
|
||||||
app.component("MagEmoji", MagEmoji);
|
app.component("MagEmoji", MagEmoji);
|
||||||
|
@ -87,6 +89,7 @@ declare module "@vue/runtime-core" {
|
||||||
RouterView: typeof RouterView;
|
RouterView: typeof RouterView;
|
||||||
Mfm: typeof Mfm;
|
Mfm: typeof Mfm;
|
||||||
MkA: typeof MkA;
|
MkA: typeof MkA;
|
||||||
|
MagSpinner: typeof MagSpinner;
|
||||||
MkAcct: typeof MkAcct;
|
MkAcct: typeof MkAcct;
|
||||||
MagAvatar: typeof MagAvatar;
|
MagAvatar: typeof MagAvatar;
|
||||||
MagEmoji: typeof MagEmoji;
|
MagEmoji: typeof MagEmoji;
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
></div>
|
></div>
|
||||||
<div class="top">
|
<div class="top">
|
||||||
<p class="name">
|
<p class="name">
|
||||||
<i class="ph-circle-notch ph-bold ph-lg fa-pulse"></i
|
<MagSpinner />{{ ctx.name }}
|
||||||
>{{ ctx.name }}
|
|
||||||
</p>
|
</p>
|
||||||
<p class="status">
|
<p class="status">
|
||||||
<span
|
<span
|
||||||
|
|
|
@ -34,6 +34,7 @@ loggingIn: "Signing In"
|
||||||
logout: "Sign Out"
|
logout: "Sign Out"
|
||||||
signup: "Sign Up"
|
signup: "Sign Up"
|
||||||
uploading: "Uploading..."
|
uploading: "Uploading..."
|
||||||
|
busy: "Busy..."
|
||||||
save: "Save"
|
save: "Save"
|
||||||
users: "Users"
|
users: "Users"
|
||||||
addUser: "Add a user"
|
addUser: "Add a user"
|
||||||
|
|
Loading…
Reference in New Issue