You've already forked AstralRinth
forked from didirus/AstralRinth
Add TailwindCSS (#1252)
* Setup TailwindCSS * Fully setup configuration * Refactor some tailwind variables
This commit is contained in:
@@ -1,129 +1,132 @@
|
||||
/* eslint-disable no-undef */
|
||||
export const useAuth = async (oldToken = null) => {
|
||||
const auth = useState('auth', () => ({
|
||||
const auth = useState("auth", () => ({
|
||||
user: null,
|
||||
token: '',
|
||||
token: "",
|
||||
headers: {},
|
||||
}))
|
||||
}));
|
||||
|
||||
if (!auth.value.user || oldToken) {
|
||||
auth.value = await initAuth(oldToken)
|
||||
auth.value = await initAuth(oldToken);
|
||||
}
|
||||
|
||||
return auth
|
||||
}
|
||||
return auth;
|
||||
};
|
||||
|
||||
export const initAuth = async (oldToken = null) => {
|
||||
const auth = {
|
||||
user: null,
|
||||
token: '',
|
||||
token: "",
|
||||
};
|
||||
|
||||
if (oldToken === "none") {
|
||||
return auth;
|
||||
}
|
||||
|
||||
if (oldToken === 'none') {
|
||||
return auth
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
const authCookie = useCookie('auth-token', {
|
||||
const route = useRoute();
|
||||
const authCookie = useCookie("auth-token", {
|
||||
maxAge: 60 * 60 * 24 * 365 * 10,
|
||||
sameSite: 'lax',
|
||||
sameSite: "lax",
|
||||
secure: true,
|
||||
httpOnly: false,
|
||||
path: '/',
|
||||
})
|
||||
path: "/",
|
||||
});
|
||||
|
||||
if (oldToken) {
|
||||
authCookie.value = oldToken
|
||||
authCookie.value = oldToken;
|
||||
}
|
||||
|
||||
if (route.query.code && !route.fullPath.includes('new_account=true')) {
|
||||
authCookie.value = route.query.code
|
||||
if (route.query.code && !route.fullPath.includes("new_account=true")) {
|
||||
authCookie.value = route.query.code;
|
||||
}
|
||||
|
||||
if (authCookie.value) {
|
||||
auth.token = authCookie.value
|
||||
auth.token = authCookie.value;
|
||||
|
||||
if (!auth.token || !auth.token.startsWith('mra_')) {
|
||||
return auth
|
||||
if (!auth.token || !auth.token.startsWith("mra_")) {
|
||||
return auth;
|
||||
}
|
||||
|
||||
try {
|
||||
auth.user = await useBaseFetch(
|
||||
'user',
|
||||
"user",
|
||||
{
|
||||
headers: {
|
||||
Authorization: auth.token,
|
||||
},
|
||||
},
|
||||
true
|
||||
)
|
||||
} catch {}
|
||||
true,
|
||||
);
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
|
||||
if (!auth.user && auth.token) {
|
||||
try {
|
||||
const session = await useBaseFetch(
|
||||
'session/refresh',
|
||||
"session/refresh",
|
||||
{
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: auth.token,
|
||||
},
|
||||
},
|
||||
true
|
||||
)
|
||||
true,
|
||||
);
|
||||
|
||||
auth.token = session.session
|
||||
authCookie.value = auth.token
|
||||
auth.token = session.session;
|
||||
authCookie.value = auth.token;
|
||||
|
||||
auth.user = await useBaseFetch(
|
||||
'user',
|
||||
"user",
|
||||
{
|
||||
headers: {
|
||||
Authorization: auth.token,
|
||||
},
|
||||
},
|
||||
true
|
||||
)
|
||||
true,
|
||||
);
|
||||
} catch {
|
||||
authCookie.value = null
|
||||
authCookie.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
return auth
|
||||
}
|
||||
return auth;
|
||||
};
|
||||
|
||||
export const getAuthUrl = (provider, redirect = '') => {
|
||||
const config = useRuntimeConfig()
|
||||
const route = useNativeRoute()
|
||||
export const getAuthUrl = (provider, redirect = "") => {
|
||||
const config = useRuntimeConfig();
|
||||
const route = useNativeRoute();
|
||||
|
||||
if (redirect === '') {
|
||||
redirect = route.path
|
||||
if (redirect === "") {
|
||||
redirect = route.path;
|
||||
}
|
||||
const fullURL = `${config.public.siteUrl}${redirect}`
|
||||
const fullURL = `${config.public.siteUrl}${redirect}`;
|
||||
|
||||
return `${config.public.apiBaseUrl}auth/init?url=${fullURL}&provider=${provider}`
|
||||
}
|
||||
return `${config.public.apiBaseUrl}auth/init?url=${fullURL}&provider=${provider}`;
|
||||
};
|
||||
|
||||
export const removeAuthProvider = async (provider) => {
|
||||
startLoading()
|
||||
startLoading();
|
||||
try {
|
||||
const auth = await useAuth()
|
||||
const auth = await useAuth();
|
||||
|
||||
await useBaseFetch('auth/provider', {
|
||||
method: 'DELETE',
|
||||
await useBaseFetch("auth/provider", {
|
||||
method: "DELETE",
|
||||
body: {
|
||||
provider,
|
||||
},
|
||||
})
|
||||
await useAuth(auth.value.token)
|
||||
});
|
||||
await useAuth(auth.value.token);
|
||||
} catch (err) {
|
||||
const data = useNuxtApp()
|
||||
const data = useNuxtApp();
|
||||
data.$notify({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
group: "main",
|
||||
title: "An error occurred",
|
||||
text: err.data.description,
|
||||
type: 'error',
|
||||
})
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
stopLoading()
|
||||
}
|
||||
stopLoading();
|
||||
};
|
||||
|
||||
@@ -1,573 +1,577 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
export const scopeMessages = defineMessages({
|
||||
userReadEmailLabel: {
|
||||
id: 'scopes.userReadEmail.label',
|
||||
defaultMessage: 'Read user email',
|
||||
id: "scopes.userReadEmail.label",
|
||||
defaultMessage: "Read user email",
|
||||
},
|
||||
userReadEmailDescription: {
|
||||
id: 'scopes.userReadEmail.description',
|
||||
defaultMessage: 'Read your email',
|
||||
id: "scopes.userReadEmail.description",
|
||||
defaultMessage: "Read your email",
|
||||
},
|
||||
userReadLabel: {
|
||||
id: 'scopes.userRead.label',
|
||||
defaultMessage: 'Read user data',
|
||||
id: "scopes.userRead.label",
|
||||
defaultMessage: "Read user data",
|
||||
},
|
||||
userReadDescription: {
|
||||
id: 'scopes.userRead.description',
|
||||
defaultMessage: 'Access your public profile information',
|
||||
id: "scopes.userRead.description",
|
||||
defaultMessage: "Access your public profile information",
|
||||
},
|
||||
userWriteLabel: {
|
||||
id: 'scopes.userWrite.label',
|
||||
defaultMessage: 'Write user data',
|
||||
id: "scopes.userWrite.label",
|
||||
defaultMessage: "Write user data",
|
||||
},
|
||||
userWriteDescription: {
|
||||
id: 'scopes.userWrite.description',
|
||||
defaultMessage: 'Write to your profile',
|
||||
id: "scopes.userWrite.description",
|
||||
defaultMessage: "Write to your profile",
|
||||
},
|
||||
userDeleteLabel: {
|
||||
id: 'scopes.userDelete.label',
|
||||
defaultMessage: 'Delete your account',
|
||||
id: "scopes.userDelete.label",
|
||||
defaultMessage: "Delete your account",
|
||||
},
|
||||
userDeleteDescription: {
|
||||
id: 'scopes.userDelete.description',
|
||||
defaultMessage: 'Delete your account',
|
||||
id: "scopes.userDelete.description",
|
||||
defaultMessage: "Delete your account",
|
||||
},
|
||||
userAuthWriteLabel: {
|
||||
id: 'scopes.userAuthWrite.label',
|
||||
defaultMessage: 'Write auth data',
|
||||
id: "scopes.userAuthWrite.label",
|
||||
defaultMessage: "Write auth data",
|
||||
},
|
||||
userAuthWriteDescription: {
|
||||
id: 'scopes.userAuthWrite.description',
|
||||
defaultMessage: 'Modify your authentication data',
|
||||
id: "scopes.userAuthWrite.description",
|
||||
defaultMessage: "Modify your authentication data",
|
||||
},
|
||||
notificationReadLabel: {
|
||||
id: 'scopes.notificationRead.label',
|
||||
defaultMessage: 'Read notifications',
|
||||
id: "scopes.notificationRead.label",
|
||||
defaultMessage: "Read notifications",
|
||||
},
|
||||
notificationReadDescription: {
|
||||
id: 'scopes.notificationRead.description',
|
||||
defaultMessage: 'Read your notifications',
|
||||
id: "scopes.notificationRead.description",
|
||||
defaultMessage: "Read your notifications",
|
||||
},
|
||||
notificationWriteLabel: {
|
||||
id: 'scopes.notificationWrite.label',
|
||||
defaultMessage: 'Write notifications',
|
||||
id: "scopes.notificationWrite.label",
|
||||
defaultMessage: "Write notifications",
|
||||
},
|
||||
notificationWriteDescription: {
|
||||
id: 'scopes.notificationWrite.description',
|
||||
defaultMessage: 'Delete/View your notifications',
|
||||
id: "scopes.notificationWrite.description",
|
||||
defaultMessage: "Delete/View your notifications",
|
||||
},
|
||||
payoutsReadLabel: {
|
||||
id: 'scopes.payoutsRead.label',
|
||||
defaultMessage: 'Read payouts',
|
||||
id: "scopes.payoutsRead.label",
|
||||
defaultMessage: "Read payouts",
|
||||
},
|
||||
payoutsReadDescription: {
|
||||
id: 'scopes.payoutsRead.description',
|
||||
defaultMessage: 'Read your payouts data',
|
||||
id: "scopes.payoutsRead.description",
|
||||
defaultMessage: "Read your payouts data",
|
||||
},
|
||||
payoutsWriteLabel: {
|
||||
id: 'scopes.payoutsWrite.label',
|
||||
defaultMessage: 'Write payouts',
|
||||
id: "scopes.payoutsWrite.label",
|
||||
defaultMessage: "Write payouts",
|
||||
},
|
||||
payoutsWriteDescription: {
|
||||
id: 'scopes.payoutsWrite.description',
|
||||
defaultMessage: 'Withdraw money',
|
||||
id: "scopes.payoutsWrite.description",
|
||||
defaultMessage: "Withdraw money",
|
||||
},
|
||||
analyticsLabel: {
|
||||
id: 'scopes.analytics.label',
|
||||
defaultMessage: 'Read analytics',
|
||||
id: "scopes.analytics.label",
|
||||
defaultMessage: "Read analytics",
|
||||
},
|
||||
analyticsDescription: {
|
||||
id: 'scopes.analytics.description',
|
||||
defaultMessage: 'Access your analytics data',
|
||||
id: "scopes.analytics.description",
|
||||
defaultMessage: "Access your analytics data",
|
||||
},
|
||||
projectCreateLabel: {
|
||||
id: 'scopes.projectCreate.label',
|
||||
defaultMessage: 'Create projects',
|
||||
id: "scopes.projectCreate.label",
|
||||
defaultMessage: "Create projects",
|
||||
},
|
||||
projectCreateDescription: {
|
||||
id: 'scopes.projectCreate.description',
|
||||
defaultMessage: 'Create new projects',
|
||||
id: "scopes.projectCreate.description",
|
||||
defaultMessage: "Create new projects",
|
||||
},
|
||||
projectReadLabel: {
|
||||
id: 'scopes.projectRead.label',
|
||||
defaultMessage: 'Read projects',
|
||||
id: "scopes.projectRead.label",
|
||||
defaultMessage: "Read projects",
|
||||
},
|
||||
projectReadDescription: {
|
||||
id: 'scopes.projectRead.description',
|
||||
defaultMessage: 'Read all your projects',
|
||||
id: "scopes.projectRead.description",
|
||||
defaultMessage: "Read all your projects",
|
||||
},
|
||||
projectWriteLabel: {
|
||||
id: 'scopes.projectWrite.label',
|
||||
defaultMessage: 'Write projects',
|
||||
id: "scopes.projectWrite.label",
|
||||
defaultMessage: "Write projects",
|
||||
},
|
||||
projectWriteDescription: {
|
||||
id: 'scopes.projectWrite.description',
|
||||
defaultMessage: 'Write to project data',
|
||||
id: "scopes.projectWrite.description",
|
||||
defaultMessage: "Write to project data",
|
||||
},
|
||||
projectDeleteLabel: {
|
||||
id: 'scopes.projectDelete.label',
|
||||
defaultMessage: 'Delete projects',
|
||||
id: "scopes.projectDelete.label",
|
||||
defaultMessage: "Delete projects",
|
||||
},
|
||||
projectDeleteDescription: {
|
||||
id: 'scopes.projectDelete.description',
|
||||
defaultMessage: 'Delete your projects',
|
||||
id: "scopes.projectDelete.description",
|
||||
defaultMessage: "Delete your projects",
|
||||
},
|
||||
versionCreateLabel: {
|
||||
id: 'scopes.versionCreate.label',
|
||||
defaultMessage: 'Create versions',
|
||||
id: "scopes.versionCreate.label",
|
||||
defaultMessage: "Create versions",
|
||||
},
|
||||
versionCreateDescription: {
|
||||
id: 'scopes.versionCreate.description',
|
||||
defaultMessage: 'Create new versions',
|
||||
id: "scopes.versionCreate.description",
|
||||
defaultMessage: "Create new versions",
|
||||
},
|
||||
versionReadLabel: {
|
||||
id: 'scopes.versionRead.label',
|
||||
defaultMessage: 'Read versions',
|
||||
id: "scopes.versionRead.label",
|
||||
defaultMessage: "Read versions",
|
||||
},
|
||||
versionReadDescription: {
|
||||
id: 'scopes.versionRead.description',
|
||||
defaultMessage: 'Read all versions',
|
||||
id: "scopes.versionRead.description",
|
||||
defaultMessage: "Read all versions",
|
||||
},
|
||||
versionWriteLabel: {
|
||||
id: 'scopes.versionWrite.label',
|
||||
defaultMessage: 'Write versions',
|
||||
id: "scopes.versionWrite.label",
|
||||
defaultMessage: "Write versions",
|
||||
},
|
||||
versionWriteDescription: {
|
||||
id: 'scopes.versionWrite.description',
|
||||
defaultMessage: 'Write to version data',
|
||||
id: "scopes.versionWrite.description",
|
||||
defaultMessage: "Write to version data",
|
||||
},
|
||||
versionDeleteLabel: {
|
||||
id: 'scopes.versionDelete.label',
|
||||
defaultMessage: 'Delete versions',
|
||||
id: "scopes.versionDelete.label",
|
||||
defaultMessage: "Delete versions",
|
||||
},
|
||||
versionDeleteDescription: {
|
||||
id: 'scopes.versionDelete.description',
|
||||
defaultMessage: 'Delete a version',
|
||||
id: "scopes.versionDelete.description",
|
||||
defaultMessage: "Delete a version",
|
||||
},
|
||||
reportCreateLabel: {
|
||||
id: 'scopes.reportCreate.label',
|
||||
defaultMessage: 'Create reports',
|
||||
id: "scopes.reportCreate.label",
|
||||
defaultMessage: "Create reports",
|
||||
},
|
||||
reportCreateDescription: {
|
||||
id: 'scopes.reportCreate.description',
|
||||
defaultMessage: 'Create reports',
|
||||
id: "scopes.reportCreate.description",
|
||||
defaultMessage: "Create reports",
|
||||
},
|
||||
reportReadLabel: {
|
||||
id: 'scopes.reportRead.label',
|
||||
defaultMessage: 'Read reports',
|
||||
id: "scopes.reportRead.label",
|
||||
defaultMessage: "Read reports",
|
||||
},
|
||||
reportReadDescription: {
|
||||
id: 'scopes.reportRead.description',
|
||||
defaultMessage: 'Read reports',
|
||||
id: "scopes.reportRead.description",
|
||||
defaultMessage: "Read reports",
|
||||
},
|
||||
reportWriteLabel: {
|
||||
id: 'scopes.reportWrite.label',
|
||||
defaultMessage: 'Write reports',
|
||||
id: "scopes.reportWrite.label",
|
||||
defaultMessage: "Write reports",
|
||||
},
|
||||
reportWriteDescription: {
|
||||
id: 'scopes.reportWrite.description',
|
||||
defaultMessage: 'Edit reports',
|
||||
id: "scopes.reportWrite.description",
|
||||
defaultMessage: "Edit reports",
|
||||
},
|
||||
reportDeleteLabel: {
|
||||
id: 'scopes.reportDelete.label',
|
||||
defaultMessage: 'Delete reports',
|
||||
id: "scopes.reportDelete.label",
|
||||
defaultMessage: "Delete reports",
|
||||
},
|
||||
reportDeleteDescription: {
|
||||
id: 'scopes.reportDelete.description',
|
||||
defaultMessage: 'Delete reports',
|
||||
id: "scopes.reportDelete.description",
|
||||
defaultMessage: "Delete reports",
|
||||
},
|
||||
threadReadLabel: {
|
||||
id: 'scopes.threadRead.label',
|
||||
defaultMessage: 'Read threads',
|
||||
id: "scopes.threadRead.label",
|
||||
defaultMessage: "Read threads",
|
||||
},
|
||||
threadReadDescription: {
|
||||
id: 'scopes.threadRead.description',
|
||||
defaultMessage: 'Read threads',
|
||||
id: "scopes.threadRead.description",
|
||||
defaultMessage: "Read threads",
|
||||
},
|
||||
threadWriteLabel: {
|
||||
id: 'scopes.threadWrite.label',
|
||||
defaultMessage: 'Write threads',
|
||||
id: "scopes.threadWrite.label",
|
||||
defaultMessage: "Write threads",
|
||||
},
|
||||
threadWriteDescription: {
|
||||
id: 'scopes.threadWrite.description',
|
||||
defaultMessage: 'Write to threads',
|
||||
id: "scopes.threadWrite.description",
|
||||
defaultMessage: "Write to threads",
|
||||
},
|
||||
patCreateLabel: {
|
||||
id: 'scopes.patCreate.label',
|
||||
defaultMessage: 'Create PATs',
|
||||
id: "scopes.patCreate.label",
|
||||
defaultMessage: "Create PATs",
|
||||
},
|
||||
patCreateDescription: {
|
||||
id: 'scopes.patCreate.description',
|
||||
defaultMessage: 'Create personal API tokens',
|
||||
id: "scopes.patCreate.description",
|
||||
defaultMessage: "Create personal API tokens",
|
||||
},
|
||||
patReadLabel: {
|
||||
id: 'scopes.patRead.label',
|
||||
defaultMessage: 'Read PATs',
|
||||
id: "scopes.patRead.label",
|
||||
defaultMessage: "Read PATs",
|
||||
},
|
||||
patReadDescription: {
|
||||
id: 'scopes.patRead.description',
|
||||
defaultMessage: 'View created API tokens',
|
||||
id: "scopes.patRead.description",
|
||||
defaultMessage: "View created API tokens",
|
||||
},
|
||||
patWriteLabel: {
|
||||
id: 'scopes.patWrite.label',
|
||||
defaultMessage: 'Write PATs',
|
||||
id: "scopes.patWrite.label",
|
||||
defaultMessage: "Write PATs",
|
||||
},
|
||||
patWriteDescription: {
|
||||
id: 'scopes.patWrite.description',
|
||||
defaultMessage: 'Edit personal API tokens',
|
||||
id: "scopes.patWrite.description",
|
||||
defaultMessage: "Edit personal API tokens",
|
||||
},
|
||||
patDeleteLabel: {
|
||||
id: 'scopes.patDelete.label',
|
||||
defaultMessage: 'Delete PATs',
|
||||
id: "scopes.patDelete.label",
|
||||
defaultMessage: "Delete PATs",
|
||||
},
|
||||
patDeleteDescription: {
|
||||
id: 'scopes.patDelete.description',
|
||||
defaultMessage: 'Delete your personal API tokens',
|
||||
id: "scopes.patDelete.description",
|
||||
defaultMessage: "Delete your personal API tokens",
|
||||
},
|
||||
sessionReadLabel: {
|
||||
id: 'scopes.sessionRead.label',
|
||||
defaultMessage: 'Read sessions',
|
||||
id: "scopes.sessionRead.label",
|
||||
defaultMessage: "Read sessions",
|
||||
},
|
||||
sessionReadDescription: {
|
||||
id: 'scopes.sessionRead.description',
|
||||
defaultMessage: 'Read active sessions',
|
||||
id: "scopes.sessionRead.description",
|
||||
defaultMessage: "Read active sessions",
|
||||
},
|
||||
sessionDeleteLabel: {
|
||||
id: 'scopes.sessionDelete.label',
|
||||
defaultMessage: 'Delete sessions',
|
||||
id: "scopes.sessionDelete.label",
|
||||
defaultMessage: "Delete sessions",
|
||||
},
|
||||
sessionDeleteDescription: {
|
||||
id: 'scopes.sessionDelete.description',
|
||||
defaultMessage: 'Delete sessions',
|
||||
id: "scopes.sessionDelete.description",
|
||||
defaultMessage: "Delete sessions",
|
||||
},
|
||||
performAnalyticsLabel: {
|
||||
id: 'scopes.performAnalytics.label',
|
||||
defaultMessage: 'Perform analytics',
|
||||
id: "scopes.performAnalytics.label",
|
||||
defaultMessage: "Perform analytics",
|
||||
},
|
||||
performAnalyticsDescription: {
|
||||
id: 'scopes.performAnalytics.description',
|
||||
defaultMessage: 'Perform analytics actions',
|
||||
id: "scopes.performAnalytics.description",
|
||||
defaultMessage: "Perform analytics actions",
|
||||
},
|
||||
collectionCreateLabel: {
|
||||
id: 'scopes.collectionCreate.label',
|
||||
defaultMessage: 'Create collections',
|
||||
id: "scopes.collectionCreate.label",
|
||||
defaultMessage: "Create collections",
|
||||
},
|
||||
collectionCreateDescription: {
|
||||
id: 'scopes.collectionCreate.description',
|
||||
defaultMessage: 'Create collections',
|
||||
id: "scopes.collectionCreate.description",
|
||||
defaultMessage: "Create collections",
|
||||
},
|
||||
collectionReadLabel: {
|
||||
id: 'scopes.collectionRead.label',
|
||||
defaultMessage: 'Read collections',
|
||||
id: "scopes.collectionRead.label",
|
||||
defaultMessage: "Read collections",
|
||||
},
|
||||
collectionReadDescription: {
|
||||
id: 'scopes.collectionRead.description',
|
||||
defaultMessage: 'Read collections',
|
||||
id: "scopes.collectionRead.description",
|
||||
defaultMessage: "Read collections",
|
||||
},
|
||||
collectionWriteLabel: {
|
||||
id: 'scopes.collectionWrite.label',
|
||||
defaultMessage: 'Write collections',
|
||||
id: "scopes.collectionWrite.label",
|
||||
defaultMessage: "Write collections",
|
||||
},
|
||||
collectionWriteDescription: {
|
||||
id: 'scopes.collectionWrite.description',
|
||||
defaultMessage: 'Write to collections',
|
||||
id: "scopes.collectionWrite.description",
|
||||
defaultMessage: "Write to collections",
|
||||
},
|
||||
collectionDeleteLabel: {
|
||||
id: 'scopes.collectionDelete.label',
|
||||
defaultMessage: 'Delete collections',
|
||||
id: "scopes.collectionDelete.label",
|
||||
defaultMessage: "Delete collections",
|
||||
},
|
||||
collectionDeleteDescription: {
|
||||
id: 'scopes.collectionDelete.description',
|
||||
defaultMessage: 'Delete collections',
|
||||
id: "scopes.collectionDelete.description",
|
||||
defaultMessage: "Delete collections",
|
||||
},
|
||||
organizationCreateLabel: {
|
||||
id: 'scopes.organizationCreate.label',
|
||||
defaultMessage: 'Create organizations',
|
||||
id: "scopes.organizationCreate.label",
|
||||
defaultMessage: "Create organizations",
|
||||
},
|
||||
organizationCreateDescription: {
|
||||
id: 'scopes.organizationCreate.description',
|
||||
defaultMessage: 'Create organizations',
|
||||
id: "scopes.organizationCreate.description",
|
||||
defaultMessage: "Create organizations",
|
||||
},
|
||||
organizationReadLabel: {
|
||||
id: 'scopes.organizationRead.label',
|
||||
defaultMessage: 'Read organizations',
|
||||
id: "scopes.organizationRead.label",
|
||||
defaultMessage: "Read organizations",
|
||||
},
|
||||
organizationReadDescription: {
|
||||
id: 'scopes.organizationRead.description',
|
||||
defaultMessage: 'Read organizations',
|
||||
id: "scopes.organizationRead.description",
|
||||
defaultMessage: "Read organizations",
|
||||
},
|
||||
organizationWriteLabel: {
|
||||
id: 'scopes.organizationWrite.label',
|
||||
defaultMessage: 'Write organizations',
|
||||
id: "scopes.organizationWrite.label",
|
||||
defaultMessage: "Write organizations",
|
||||
},
|
||||
organizationWriteDescription: {
|
||||
id: 'scopes.organizationWrite.description',
|
||||
defaultMessage: 'Write to organizations',
|
||||
id: "scopes.organizationWrite.description",
|
||||
defaultMessage: "Write to organizations",
|
||||
},
|
||||
organizationDeleteLabel: {
|
||||
id: 'scopes.organizationDelete.label',
|
||||
defaultMessage: 'Delete organizations',
|
||||
id: "scopes.organizationDelete.label",
|
||||
defaultMessage: "Delete organizations",
|
||||
},
|
||||
organizationDeleteDescription: {
|
||||
id: 'scopes.organizationDelete.description',
|
||||
defaultMessage: 'Delete organizations',
|
||||
id: "scopes.organizationDelete.description",
|
||||
defaultMessage: "Delete organizations",
|
||||
},
|
||||
sessionAccessLabel: {
|
||||
id: 'scopes.sessionAccess.label',
|
||||
defaultMessage: 'Access sessions',
|
||||
id: "scopes.sessionAccess.label",
|
||||
defaultMessage: "Access sessions",
|
||||
},
|
||||
sessionAccessDescription: {
|
||||
id: 'scopes.sessionAccess.description',
|
||||
defaultMessage: 'Access modrinth-issued sessions',
|
||||
id: "scopes.sessionAccess.description",
|
||||
defaultMessage: "Access modrinth-issued sessions",
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
const scopeDefinitions = [
|
||||
{
|
||||
id: 'USER_READ_EMAIL',
|
||||
id: "USER_READ_EMAIL",
|
||||
value: BigInt(1) << BigInt(0),
|
||||
label: scopeMessages.userReadEmailLabel,
|
||||
desc: scopeMessages.userReadEmailDescription,
|
||||
},
|
||||
{
|
||||
id: 'USER_READ',
|
||||
id: "USER_READ",
|
||||
value: BigInt(1) << BigInt(1),
|
||||
label: scopeMessages.userReadLabel,
|
||||
desc: scopeMessages.userReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'USER_WRITE',
|
||||
id: "USER_WRITE",
|
||||
value: BigInt(1) << BigInt(2),
|
||||
label: scopeMessages.userWriteLabel,
|
||||
desc: scopeMessages.userWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'USER_DELETE',
|
||||
id: "USER_DELETE",
|
||||
value: BigInt(1) << BigInt(3),
|
||||
label: scopeMessages.userDeleteLabel,
|
||||
desc: scopeMessages.userDeleteDescription,
|
||||
},
|
||||
{
|
||||
id: 'USER_AUTH_WRITE',
|
||||
id: "USER_AUTH_WRITE",
|
||||
value: BigInt(1) << BigInt(4),
|
||||
label: scopeMessages.userAuthWriteLabel,
|
||||
desc: scopeMessages.userAuthWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'NOTIFICATION_READ',
|
||||
id: "NOTIFICATION_READ",
|
||||
value: BigInt(1) << BigInt(5),
|
||||
label: scopeMessages.notificationReadLabel,
|
||||
desc: scopeMessages.notificationReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'NOTIFICATION_WRITE',
|
||||
id: "NOTIFICATION_WRITE",
|
||||
value: BigInt(1) << BigInt(6),
|
||||
label: scopeMessages.notificationWriteLabel,
|
||||
desc: scopeMessages.notificationWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'PAYOUTS_READ',
|
||||
id: "PAYOUTS_READ",
|
||||
value: BigInt(1) << BigInt(7),
|
||||
label: scopeMessages.payoutsReadLabel,
|
||||
desc: scopeMessages.payoutsReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'PAYOUTS_WRITE',
|
||||
id: "PAYOUTS_WRITE",
|
||||
value: BigInt(1) << BigInt(8),
|
||||
label: scopeMessages.payoutsWriteLabel,
|
||||
desc: scopeMessages.payoutsWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'ANALYTICS',
|
||||
id: "ANALYTICS",
|
||||
value: BigInt(1) << BigInt(9),
|
||||
label: scopeMessages.analyticsLabel,
|
||||
desc: scopeMessages.analyticsDescription,
|
||||
},
|
||||
{
|
||||
id: 'PROJECT_CREATE',
|
||||
id: "PROJECT_CREATE",
|
||||
value: BigInt(1) << BigInt(10),
|
||||
label: scopeMessages.projectCreateLabel,
|
||||
desc: scopeMessages.projectCreateDescription,
|
||||
},
|
||||
{
|
||||
id: 'PROJECT_READ',
|
||||
id: "PROJECT_READ",
|
||||
value: BigInt(1) << BigInt(11),
|
||||
label: scopeMessages.projectReadLabel,
|
||||
desc: scopeMessages.projectReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'PROJECT_WRITE',
|
||||
id: "PROJECT_WRITE",
|
||||
value: BigInt(1) << BigInt(12),
|
||||
label: scopeMessages.projectWriteLabel,
|
||||
desc: scopeMessages.projectWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'PROJECT_DELETE',
|
||||
id: "PROJECT_DELETE",
|
||||
value: BigInt(1) << BigInt(13),
|
||||
label: scopeMessages.projectDeleteLabel,
|
||||
desc: scopeMessages.projectDeleteDescription,
|
||||
},
|
||||
{
|
||||
id: 'VERSION_CREATE',
|
||||
id: "VERSION_CREATE",
|
||||
value: BigInt(1) << BigInt(14),
|
||||
label: scopeMessages.versionCreateLabel,
|
||||
desc: scopeMessages.versionCreateDescription,
|
||||
},
|
||||
{
|
||||
id: 'VERSION_READ',
|
||||
id: "VERSION_READ",
|
||||
value: BigInt(1) << BigInt(15),
|
||||
label: scopeMessages.versionReadLabel,
|
||||
desc: scopeMessages.versionReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'VERSION_WRITE',
|
||||
id: "VERSION_WRITE",
|
||||
value: BigInt(1) << BigInt(16),
|
||||
label: scopeMessages.versionWriteLabel,
|
||||
desc: scopeMessages.versionWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'VERSION_DELETE',
|
||||
id: "VERSION_DELETE",
|
||||
value: BigInt(1) << BigInt(17),
|
||||
label: scopeMessages.versionDeleteLabel,
|
||||
desc: scopeMessages.versionDeleteDescription,
|
||||
},
|
||||
{
|
||||
id: 'REPORT_CREATE',
|
||||
id: "REPORT_CREATE",
|
||||
value: BigInt(1) << BigInt(18),
|
||||
label: scopeMessages.reportCreateLabel,
|
||||
desc: scopeMessages.reportCreateDescription,
|
||||
},
|
||||
{
|
||||
id: 'REPORT_READ',
|
||||
id: "REPORT_READ",
|
||||
value: BigInt(1) << BigInt(19),
|
||||
label: scopeMessages.reportReadLabel,
|
||||
desc: scopeMessages.reportReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'REPORT_WRITE',
|
||||
id: "REPORT_WRITE",
|
||||
value: BigInt(1) << BigInt(20),
|
||||
label: scopeMessages.reportWriteLabel,
|
||||
desc: scopeMessages.reportWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'REPORT_DELETE',
|
||||
id: "REPORT_DELETE",
|
||||
value: BigInt(1) << BigInt(21),
|
||||
label: scopeMessages.reportDeleteLabel,
|
||||
desc: scopeMessages.reportDeleteDescription,
|
||||
},
|
||||
{
|
||||
id: 'THREAD_READ',
|
||||
id: "THREAD_READ",
|
||||
value: BigInt(1) << BigInt(22),
|
||||
label: scopeMessages.threadReadLabel,
|
||||
desc: scopeMessages.threadReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'THREAD_WRITE',
|
||||
id: "THREAD_WRITE",
|
||||
value: BigInt(1) << BigInt(23),
|
||||
label: scopeMessages.threadWriteLabel,
|
||||
desc: scopeMessages.threadWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'PAT_CREATE',
|
||||
id: "PAT_CREATE",
|
||||
value: BigInt(1) << BigInt(24),
|
||||
label: scopeMessages.patCreateLabel,
|
||||
desc: scopeMessages.patCreateDescription,
|
||||
},
|
||||
{
|
||||
id: 'PAT_READ',
|
||||
id: "PAT_READ",
|
||||
value: BigInt(1) << BigInt(25),
|
||||
label: scopeMessages.patReadLabel,
|
||||
desc: scopeMessages.patReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'PAT_WRITE',
|
||||
id: "PAT_WRITE",
|
||||
value: BigInt(1) << BigInt(26),
|
||||
label: scopeMessages.patWriteLabel,
|
||||
desc: scopeMessages.patWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'PAT_DELETE',
|
||||
id: "PAT_DELETE",
|
||||
value: BigInt(1) << BigInt(27),
|
||||
label: scopeMessages.patDeleteLabel,
|
||||
desc: scopeMessages.patDeleteDescription,
|
||||
},
|
||||
{
|
||||
id: 'SESSION_READ',
|
||||
id: "SESSION_READ",
|
||||
value: BigInt(1) << BigInt(28),
|
||||
label: scopeMessages.sessionReadLabel,
|
||||
desc: scopeMessages.sessionReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'SESSION_DELETE',
|
||||
id: "SESSION_DELETE",
|
||||
value: BigInt(1) << BigInt(29),
|
||||
label: scopeMessages.sessionDeleteLabel,
|
||||
desc: scopeMessages.sessionDeleteDescription,
|
||||
},
|
||||
{
|
||||
id: 'PERFORM_ANALYTICS',
|
||||
id: "PERFORM_ANALYTICS",
|
||||
value: BigInt(1) << BigInt(30),
|
||||
label: scopeMessages.performAnalyticsLabel,
|
||||
desc: scopeMessages.performAnalyticsDescription,
|
||||
},
|
||||
{
|
||||
id: 'COLLECTION_CREATE',
|
||||
id: "COLLECTION_CREATE",
|
||||
value: BigInt(1) << BigInt(31),
|
||||
label: scopeMessages.collectionCreateLabel,
|
||||
desc: scopeMessages.collectionCreateDescription,
|
||||
},
|
||||
{
|
||||
id: 'COLLECTION_READ',
|
||||
id: "COLLECTION_READ",
|
||||
value: BigInt(1) << BigInt(32),
|
||||
label: scopeMessages.collectionReadLabel,
|
||||
desc: scopeMessages.collectionReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'COLLECTION_WRITE',
|
||||
id: "COLLECTION_WRITE",
|
||||
value: BigInt(1) << BigInt(33),
|
||||
label: scopeMessages.collectionWriteLabel,
|
||||
desc: scopeMessages.collectionWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'COLLECTION_DELETE',
|
||||
id: "COLLECTION_DELETE",
|
||||
value: BigInt(1) << BigInt(34),
|
||||
label: scopeMessages.collectionDeleteLabel,
|
||||
desc: scopeMessages.collectionDeleteDescription,
|
||||
},
|
||||
{
|
||||
id: 'ORGANIZATION_CREATE',
|
||||
id: "ORGANIZATION_CREATE",
|
||||
value: BigInt(1) << BigInt(35),
|
||||
label: scopeMessages.organizationCreateLabel,
|
||||
desc: scopeMessages.organizationCreateDescription,
|
||||
},
|
||||
{
|
||||
id: 'ORGANIZATION_READ',
|
||||
id: "ORGANIZATION_READ",
|
||||
value: BigInt(1) << BigInt(36),
|
||||
label: scopeMessages.organizationReadLabel,
|
||||
desc: scopeMessages.organizationReadDescription,
|
||||
},
|
||||
{
|
||||
id: 'ORGANIZATION_WRITE',
|
||||
id: "ORGANIZATION_WRITE",
|
||||
value: BigInt(1) << BigInt(37),
|
||||
label: scopeMessages.organizationWriteLabel,
|
||||
desc: scopeMessages.organizationWriteDescription,
|
||||
},
|
||||
{
|
||||
id: 'ORGANIZATION_DELETE',
|
||||
id: "ORGANIZATION_DELETE",
|
||||
value: BigInt(1) << BigInt(38),
|
||||
label: scopeMessages.organizationDeleteLabel,
|
||||
desc: scopeMessages.organizationDeleteDescription,
|
||||
},
|
||||
{
|
||||
id: 'SESSION_ACCESS',
|
||||
id: "SESSION_ACCESS",
|
||||
value: BigInt(1) << BigInt(39),
|
||||
label: scopeMessages.sessionAccessLabel,
|
||||
desc: scopeMessages.sessionAccessDescription,
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
const Scopes = scopeDefinitions.reduce((acc, scope) => {
|
||||
acc[scope.id] = scope.value
|
||||
return acc
|
||||
}, {} as Record<string, bigint>)
|
||||
const Scopes = scopeDefinitions.reduce(
|
||||
(acc, scope) => {
|
||||
acc[scope.id] = scope.value;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, bigint>,
|
||||
);
|
||||
|
||||
export const restrictedScopes = [
|
||||
Scopes.PAT_READ,
|
||||
@@ -580,18 +584,18 @@ export const restrictedScopes = [
|
||||
Scopes.USER_AUTH_WRITE,
|
||||
Scopes.USER_DELETE,
|
||||
Scopes.PERFORM_ANALYTICS,
|
||||
]
|
||||
];
|
||||
|
||||
export const scopeList = Object.entries(Scopes)
|
||||
.filter(([_, value]) => !restrictedScopes.includes(value))
|
||||
.map(([key, _]) => key)
|
||||
.map(([key, _]) => key);
|
||||
|
||||
export const getScopeValue = (scope: string) => {
|
||||
return Scopes[scope]
|
||||
}
|
||||
return Scopes[scope];
|
||||
};
|
||||
|
||||
export const encodeScopes = (scopes: string[]) => {
|
||||
let scopeFlag = BigInt(0)
|
||||
let scopeFlag = BigInt(0);
|
||||
|
||||
// We iterate over the provided scopes
|
||||
for (const scope of scopes) {
|
||||
@@ -599,77 +603,77 @@ export const encodeScopes = (scopes: string[]) => {
|
||||
for (const [scopeName, scopeFlagValue] of Object.entries(Scopes)) {
|
||||
// If the scope name is the same as the provided scope, add the scope flag to the scopeFlag variable
|
||||
if (scopeName === scope) {
|
||||
scopeFlag = scopeFlag | scopeFlagValue
|
||||
scopeFlag = scopeFlag | scopeFlagValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scopeFlag
|
||||
}
|
||||
return scopeFlag;
|
||||
};
|
||||
|
||||
export const decodeScopes = (scopes: bigint | number) => {
|
||||
if (typeof scopes === 'number') {
|
||||
scopes = BigInt(scopes)
|
||||
if (typeof scopes === "number") {
|
||||
scopes = BigInt(scopes);
|
||||
}
|
||||
|
||||
const authorizedScopes = []
|
||||
const authorizedScopes = [];
|
||||
|
||||
// We iterate over the entries of the Scopes object
|
||||
for (const [scopeName, scopeFlag] of Object.entries(Scopes)) {
|
||||
// If the scope flag is present in the provided number, add the scope name to the list
|
||||
if ((scopes & scopeFlag) === scopeFlag) {
|
||||
authorizedScopes.push(scopeName)
|
||||
authorizedScopes.push(scopeName);
|
||||
}
|
||||
}
|
||||
|
||||
return authorizedScopes
|
||||
}
|
||||
return authorizedScopes;
|
||||
};
|
||||
|
||||
export const hasScope = (scopes: bigint, scope: string) => {
|
||||
const authorizedScopes = decodeScopes(scopes)
|
||||
return authorizedScopes.includes(scope)
|
||||
}
|
||||
const authorizedScopes = decodeScopes(scopes);
|
||||
return authorizedScopes.includes(scope);
|
||||
};
|
||||
|
||||
export const toggleScope = (scopes: bigint, scope: string) => {
|
||||
const authorizedScopes = decodeScopes(scopes)
|
||||
const authorizedScopes = decodeScopes(scopes);
|
||||
if (authorizedScopes.includes(scope)) {
|
||||
return encodeScopes(authorizedScopes.filter((authorizedScope) => authorizedScope !== scope))
|
||||
return encodeScopes(authorizedScopes.filter((authorizedScope) => authorizedScope !== scope));
|
||||
} else {
|
||||
return encodeScopes([...authorizedScopes, scope])
|
||||
return encodeScopes([...authorizedScopes, scope]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const useScopes = () => {
|
||||
const { formatMessage } = useVIntl()
|
||||
const { formatMessage } = useVIntl();
|
||||
|
||||
const scopesToDefinitions = (scopes: bigint) => {
|
||||
const authorizedScopes = decodeScopes(scopes)
|
||||
const authorizedScopes = decodeScopes(scopes);
|
||||
return authorizedScopes.map((scope) => {
|
||||
const scopeDefinition = scopeDefinitions.find(
|
||||
(scopeDefinition) => scopeDefinition.id === scope
|
||||
)
|
||||
(scopeDefinition) => scopeDefinition.id === scope,
|
||||
);
|
||||
if (!scopeDefinition) {
|
||||
throw new Error(`Scope ${scope} not found`)
|
||||
throw new Error(`Scope ${scope} not found`);
|
||||
}
|
||||
return formatMessage(scopeDefinition.desc)
|
||||
})
|
||||
}
|
||||
return formatMessage(scopeDefinition.desc);
|
||||
});
|
||||
};
|
||||
|
||||
const scopesToLabels = (scopes: bigint) => {
|
||||
const authorizedScopes = decodeScopes(scopes)
|
||||
const authorizedScopes = decodeScopes(scopes);
|
||||
return authorizedScopes.map((scope) => {
|
||||
const scopeDefinition = scopeDefinitions.find(
|
||||
(scopeDefinition) => scopeDefinition.id === scope
|
||||
)
|
||||
(scopeDefinition) => scopeDefinition.id === scope,
|
||||
);
|
||||
if (!scopeDefinition) {
|
||||
throw new Error(`Scope ${scope} not found`)
|
||||
throw new Error(`Scope ${scope} not found`);
|
||||
}
|
||||
return formatMessage(scopeDefinition.label)
|
||||
})
|
||||
}
|
||||
return formatMessage(scopeDefinition.label);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
scopesToDefinitions,
|
||||
scopesToLabels,
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export type AutoRef<T> = [T] extends [(...args: any[]) => any]
|
||||
? Ref<T> | (() => T)
|
||||
: T | Ref<T> | (() => T)
|
||||
: T | Ref<T> | (() => T);
|
||||
|
||||
/**
|
||||
* Accepts a value directly, a ref with the value or a getter function and returns a Vue ref.
|
||||
@@ -8,6 +8,6 @@ export type AutoRef<T> = [T] extends [(...args: any[]) => any]
|
||||
* @returns Either the original or newly created ref.
|
||||
*/
|
||||
export function useAutoRef<T>(value: AutoRef<T>): Ref<T> {
|
||||
if (typeof value === 'function') return computed(() => value())
|
||||
return isRef(value) ? value : ref(value as any)
|
||||
if (typeof value === "function") return computed(() => value());
|
||||
return isRef(value) ? value : ref(value as any);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { createFormatter, type Formatter } from '@vintl/compact-number'
|
||||
import type { IntlController } from '@vintl/vintl/controller'
|
||||
import { createFormatter, type Formatter } from "@vintl/compact-number";
|
||||
import type { IntlController } from "@vintl/vintl/controller";
|
||||
|
||||
const formatters = new WeakMap<IntlController<any>, Formatter>()
|
||||
const formatters = new WeakMap<IntlController<any>, Formatter>();
|
||||
|
||||
export function useCompactNumber(): Formatter {
|
||||
const vintl = useVIntl()
|
||||
const vintl = useVIntl();
|
||||
|
||||
let formatter = formatters.get(vintl)
|
||||
let formatter = formatters.get(vintl);
|
||||
|
||||
if (formatter == null) {
|
||||
const formatterRef = computed(() => createFormatter(vintl.intl))
|
||||
formatter = (value, options) => formatterRef.value(value, options)
|
||||
formatters.set(vintl, formatter)
|
||||
const formatterRef = computed(() => createFormatter(vintl.intl));
|
||||
formatter = (value, options) => formatterRef.value(value, options);
|
||||
formatters.set(vintl, formatter);
|
||||
}
|
||||
|
||||
return formatter
|
||||
return formatter;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/* eslint-disable no-undef */
|
||||
export const useCosmetics = () =>
|
||||
useState('cosmetics', () => {
|
||||
const cosmetics = useCookie('cosmetics', {
|
||||
useState("cosmetics", () => {
|
||||
const cosmetics = useCookie("cosmetics", {
|
||||
maxAge: 60 * 60 * 24 * 365 * 10,
|
||||
sameSite: 'lax',
|
||||
sameSite: "lax",
|
||||
secure: true,
|
||||
httpOnly: false,
|
||||
path: '/',
|
||||
})
|
||||
path: "/",
|
||||
});
|
||||
|
||||
if (!cosmetics.value) {
|
||||
cosmetics.value = {
|
||||
@@ -16,37 +17,37 @@ export const useCosmetics = () =>
|
||||
externalLinksNewTab: true,
|
||||
notUsingBlockers: false,
|
||||
hideModrinthAppPromos: false,
|
||||
preferredDarkTheme: 'dark',
|
||||
preferredDarkTheme: "dark",
|
||||
searchDisplayMode: {
|
||||
mod: 'list',
|
||||
plugin: 'list',
|
||||
resourcepack: 'gallery',
|
||||
modpack: 'list',
|
||||
shader: 'gallery',
|
||||
datapack: 'list',
|
||||
user: 'list',
|
||||
collection: 'list',
|
||||
mod: "list",
|
||||
plugin: "list",
|
||||
resourcepack: "gallery",
|
||||
modpack: "list",
|
||||
shader: "gallery",
|
||||
datapack: "list",
|
||||
user: "list",
|
||||
collection: "list",
|
||||
},
|
||||
hideStagingBanner: false,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return cosmetics.value
|
||||
})
|
||||
return cosmetics.value;
|
||||
});
|
||||
|
||||
export const saveCosmetics = () => {
|
||||
const cosmetics = useCosmetics()
|
||||
const cosmetics = useCosmetics();
|
||||
|
||||
console.log('SAVING COSMETICS:')
|
||||
console.log(cosmetics)
|
||||
console.log("SAVING COSMETICS:");
|
||||
console.log(cosmetics);
|
||||
|
||||
const cosmeticsCookie = useCookie('cosmetics', {
|
||||
const cosmeticsCookie = useCookie("cosmetics", {
|
||||
maxAge: 60 * 60 * 24 * 365 * 10,
|
||||
sameSite: 'lax',
|
||||
sameSite: "lax",
|
||||
secure: true,
|
||||
httpOnly: false,
|
||||
path: '/',
|
||||
})
|
||||
path: "/",
|
||||
});
|
||||
|
||||
cosmeticsCookie.value = cosmetics.value
|
||||
}
|
||||
cosmeticsCookie.value = cosmetics.value;
|
||||
};
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
/* eslint-disable no-undef */
|
||||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
export const useCurrentDate = () => useState('currentDate', () => Date.now())
|
||||
export const useCurrentDate = () => useState("currentDate", () => Date.now());
|
||||
|
||||
export const updateCurrentDate = () => {
|
||||
const currentDate = useCurrentDate()
|
||||
const currentDate = useCurrentDate();
|
||||
|
||||
currentDate.value = Date.now()
|
||||
}
|
||||
currentDate.value = Date.now();
|
||||
};
|
||||
|
||||
export const fromNow = (date) => {
|
||||
const currentDate = useCurrentDate()
|
||||
return dayjs(date).from(currentDate.value)
|
||||
}
|
||||
const currentDate = useCurrentDate();
|
||||
return dayjs(date).from(currentDate.value);
|
||||
};
|
||||
|
||||
@@ -1,91 +1,91 @@
|
||||
import { useAutoRef, type AutoRef } from './auto-ref.ts'
|
||||
import { useAutoRef, type AutoRef } from "./auto-ref.ts";
|
||||
|
||||
const safeTags = new Map<string, string>()
|
||||
const safeTags = new Map<string, string>();
|
||||
|
||||
function safeTagFor(locale: string) {
|
||||
let safeTag = safeTags.get(locale)
|
||||
let safeTag = safeTags.get(locale);
|
||||
if (safeTag == null) {
|
||||
safeTag = new Intl.Locale(locale).baseName
|
||||
safeTags.set(locale, safeTag)
|
||||
safeTag = new Intl.Locale(locale).baseName;
|
||||
safeTags.set(locale, safeTag);
|
||||
}
|
||||
return safeTag
|
||||
return safeTag;
|
||||
}
|
||||
|
||||
type DisplayNamesWrapper = Intl.DisplayNames & {
|
||||
of(tag: string): string | undefined
|
||||
}
|
||||
of(tag: string): string | undefined;
|
||||
};
|
||||
|
||||
const displayNamesDicts = new Map<string, DisplayNamesWrapper>()
|
||||
const displayNamesDicts = new Map<string, DisplayNamesWrapper>();
|
||||
|
||||
function getWrapperKey(locale: string, options: Intl.DisplayNamesOptions) {
|
||||
return JSON.stringify({ ...options, locale })
|
||||
return JSON.stringify({ ...options, locale });
|
||||
}
|
||||
|
||||
export function createDisplayNames(
|
||||
locale: string,
|
||||
options: Intl.DisplayNamesOptions = { type: 'language' }
|
||||
options: Intl.DisplayNamesOptions = { type: "language" },
|
||||
) {
|
||||
const wrapperKey = getWrapperKey(locale, options)
|
||||
let wrapper = displayNamesDicts.get(wrapperKey)
|
||||
const wrapperKey = getWrapperKey(locale, options);
|
||||
let wrapper = displayNamesDicts.get(wrapperKey);
|
||||
|
||||
if (wrapper == null) {
|
||||
const dict = new Intl.DisplayNames(locale, options)
|
||||
const dict = new Intl.DisplayNames(locale, options);
|
||||
|
||||
const badTags: string[] = []
|
||||
const badTags: string[] = [];
|
||||
|
||||
wrapper = {
|
||||
resolvedOptions() {
|
||||
return dict.resolvedOptions()
|
||||
return dict.resolvedOptions();
|
||||
},
|
||||
of(tag: string) {
|
||||
let attempt = 0
|
||||
let attempt = 0;
|
||||
|
||||
// eslint-disable-next-line no-labels
|
||||
lookupLoop: do {
|
||||
let lookup: string
|
||||
let lookup: string;
|
||||
switch (attempt) {
|
||||
case 0:
|
||||
lookup = tag
|
||||
break
|
||||
lookup = tag;
|
||||
break;
|
||||
case 1:
|
||||
lookup = safeTagFor(tag)
|
||||
break
|
||||
lookup = safeTagFor(tag);
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line no-labels
|
||||
break lookupLoop
|
||||
break lookupLoop;
|
||||
}
|
||||
|
||||
if (badTags.includes(lookup)) continue
|
||||
if (badTags.includes(lookup)) continue;
|
||||
|
||||
try {
|
||||
return dict.of(lookup)
|
||||
return dict.of(lookup);
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
`Failed to get display name for ${lookup} using dictionary for ${
|
||||
this.resolvedOptions().locale
|
||||
}`
|
||||
)
|
||||
badTags.push(lookup)
|
||||
continue
|
||||
}`,
|
||||
);
|
||||
badTags.push(lookup);
|
||||
continue;
|
||||
}
|
||||
} while (++attempt < 5)
|
||||
} while (++attempt < 5);
|
||||
|
||||
return undefined
|
||||
return undefined;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
displayNamesDicts.set(wrapperKey, wrapper)
|
||||
displayNamesDicts.set(wrapperKey, wrapper);
|
||||
}
|
||||
|
||||
return wrapper
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
export function useDisplayNames(
|
||||
locale: AutoRef<string>,
|
||||
options?: AutoRef<Intl.DisplayNamesOptions | undefined>
|
||||
options?: AutoRef<Intl.DisplayNamesOptions | undefined>,
|
||||
) {
|
||||
const $locale = useAutoRef(locale)
|
||||
const $options = useAutoRef(options)
|
||||
const $locale = useAutoRef(locale);
|
||||
const $options = useAutoRef(options);
|
||||
|
||||
return computed(() => createDisplayNames($locale.value, $options.value))
|
||||
return computed(() => createDisplayNames($locale.value, $options.value));
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import type { CookieOptions } from '#app'
|
||||
import type { CookieOptions } from "#app";
|
||||
|
||||
export type ProjectDisplayMode = 'list' | 'grid' | 'gallery'
|
||||
export type DarkColorTheme = 'dark' | 'oled' | 'retro'
|
||||
export type ProjectDisplayMode = "list" | "grid" | "gallery";
|
||||
export type DarkColorTheme = "dark" | "oled" | "retro";
|
||||
|
||||
export interface NumberFlag {
|
||||
min: number
|
||||
max: number
|
||||
min: number;
|
||||
max: number;
|
||||
}
|
||||
|
||||
export type BooleanFlag = boolean
|
||||
export type BooleanFlag = boolean;
|
||||
|
||||
export type RadioFlag = ProjectDisplayMode | DarkColorTheme
|
||||
export type RadioFlag = ProjectDisplayMode | DarkColorTheme;
|
||||
|
||||
export type FlagValue = BooleanFlag /* | NumberFlag | RadioFlag */
|
||||
export type FlagValue = BooleanFlag; /* | NumberFlag | RadioFlag */
|
||||
|
||||
const validateValues = <K extends PropertyKey>(flags: Record<K, FlagValue>) => flags
|
||||
const validateValues = <K extends PropertyKey>(flags: Record<K, FlagValue>) => flags;
|
||||
|
||||
export const DEFAULT_FEATURE_FLAGS = validateValues({
|
||||
// Developer flags
|
||||
@@ -48,58 +48,58 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({
|
||||
// dataPackSearchDisplayMode: 'list',
|
||||
// userProjectDisplayMode: 'list',
|
||||
// collectionProjectDisplayMode: 'list',
|
||||
} as const)
|
||||
} as const);
|
||||
|
||||
export type FeatureFlag = keyof typeof DEFAULT_FEATURE_FLAGS
|
||||
export type FeatureFlag = keyof typeof DEFAULT_FEATURE_FLAGS;
|
||||
|
||||
export type AllFeatureFlags = {
|
||||
[key in FeatureFlag]: (typeof DEFAULT_FEATURE_FLAGS)[key]
|
||||
}
|
||||
[key in FeatureFlag]: (typeof DEFAULT_FEATURE_FLAGS)[key];
|
||||
};
|
||||
|
||||
export type PartialFeatureFlags = Partial<AllFeatureFlags>
|
||||
export type PartialFeatureFlags = Partial<AllFeatureFlags>;
|
||||
|
||||
const COOKIE_OPTIONS = {
|
||||
maxAge: 60 * 60 * 24 * 365 * 10,
|
||||
sameSite: 'lax',
|
||||
sameSite: "lax",
|
||||
secure: true,
|
||||
httpOnly: false,
|
||||
path: '/',
|
||||
} satisfies CookieOptions<PartialFeatureFlags>
|
||||
path: "/",
|
||||
} satisfies CookieOptions<PartialFeatureFlags>;
|
||||
|
||||
export const useFeatureFlags = () =>
|
||||
useState<AllFeatureFlags>('featureFlags', () => {
|
||||
const config = useRuntimeConfig()
|
||||
useState<AllFeatureFlags>("featureFlags", () => {
|
||||
const config = useRuntimeConfig();
|
||||
|
||||
const savedFlags = useCookie<PartialFeatureFlags>('featureFlags', COOKIE_OPTIONS)
|
||||
const savedFlags = useCookie<PartialFeatureFlags>("featureFlags", COOKIE_OPTIONS);
|
||||
|
||||
if (!savedFlags.value) {
|
||||
savedFlags.value = {}
|
||||
savedFlags.value = {};
|
||||
}
|
||||
|
||||
const flags: AllFeatureFlags = JSON.parse(JSON.stringify(DEFAULT_FEATURE_FLAGS))
|
||||
const flags: AllFeatureFlags = JSON.parse(JSON.stringify(DEFAULT_FEATURE_FLAGS));
|
||||
|
||||
const overrides = config.public.featureFlagOverrides as PartialFeatureFlags
|
||||
const overrides = config.public.featureFlagOverrides as PartialFeatureFlags;
|
||||
for (const key in overrides) {
|
||||
if (key in flags) {
|
||||
const flag = key as FeatureFlag
|
||||
const value = overrides[flag] as (typeof flags)[FeatureFlag]
|
||||
flags[flag] = value
|
||||
const flag = key as FeatureFlag;
|
||||
const value = overrides[flag] as (typeof flags)[FeatureFlag];
|
||||
flags[flag] = value;
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in savedFlags.value) {
|
||||
if (key in flags) {
|
||||
const flag = key as FeatureFlag
|
||||
const value = savedFlags.value[flag] as (typeof flags)[FeatureFlag]
|
||||
flags[flag] = value
|
||||
const flag = key as FeatureFlag;
|
||||
const value = savedFlags.value[flag] as (typeof flags)[FeatureFlag];
|
||||
flags[flag] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return flags
|
||||
})
|
||||
return flags;
|
||||
});
|
||||
|
||||
export const saveFeatureFlags = () => {
|
||||
const flags = useFeatureFlags()
|
||||
const cookie = useCookie<PartialFeatureFlags>('featureFlags', COOKIE_OPTIONS)
|
||||
cookie.value = flags.value
|
||||
}
|
||||
const flags = useFeatureFlags();
|
||||
const cookie = useCookie<PartialFeatureFlags>("featureFlags", COOKIE_OPTIONS);
|
||||
cookie.value = flags.value;
|
||||
};
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
/* eslint-disable no-undef */
|
||||
export const useBaseFetch = async (url, options = {}, skipAuth = false) => {
|
||||
const config = useRuntimeConfig()
|
||||
let base = process.server ? config.apiBaseUrl : config.public.apiBaseUrl
|
||||
const config = useRuntimeConfig();
|
||||
let base = process.server ? config.apiBaseUrl : config.public.apiBaseUrl;
|
||||
|
||||
if (!options.headers) {
|
||||
options.headers = {}
|
||||
options.headers = {};
|
||||
}
|
||||
|
||||
if (process.server) {
|
||||
options.headers['x-ratelimit-key'] = config.rateLimitKey
|
||||
options.headers["x-ratelimit-key"] = config.rateLimitKey;
|
||||
}
|
||||
|
||||
if (!skipAuth) {
|
||||
const auth = await useAuth()
|
||||
const auth = await useAuth();
|
||||
|
||||
options.headers.Authorization = auth.value.token
|
||||
options.headers.Authorization = auth.value.token;
|
||||
}
|
||||
|
||||
if (options.apiVersion || options.internal) {
|
||||
// Base may end in /vD/ or /vD. We would need to replace the digit with the new version number
|
||||
// and keep the trailing slash if it exists
|
||||
const baseVersion = base.match(/\/v\d\//)
|
||||
const baseVersion = base.match(/\/v\d\//);
|
||||
|
||||
const replaceStr = options.internal ? `/_internal/` : `/v${options.apiVersion}/`
|
||||
const replaceStr = options.internal ? `/_internal/` : `/v${options.apiVersion}/`;
|
||||
|
||||
if (baseVersion) {
|
||||
base = base.replace(baseVersion[0], replaceStr)
|
||||
base = base.replace(baseVersion[0], replaceStr);
|
||||
} else {
|
||||
base = base.replace(/\/v\d$/, replaceStr)
|
||||
base = base.replace(/\/v\d$/, replaceStr);
|
||||
}
|
||||
|
||||
delete options.apiVersion
|
||||
delete options.apiVersion;
|
||||
}
|
||||
|
||||
return await $fetch(`${base}${url}`, options)
|
||||
}
|
||||
return await $fetch(`${base}${url}`, options);
|
||||
};
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { createFormatter, type Formatter } from '@vintl/how-ago'
|
||||
import type { IntlController } from '@vintl/vintl/controller'
|
||||
import { createFormatter, type Formatter } from "@vintl/how-ago";
|
||||
import type { IntlController } from "@vintl/vintl/controller";
|
||||
|
||||
const formatters = new WeakMap<IntlController<any>, Formatter>()
|
||||
const formatters = new WeakMap<IntlController<any>, Formatter>();
|
||||
|
||||
export function useRelativeTime(): Formatter {
|
||||
const vintl = useVIntl()
|
||||
const vintl = useVIntl();
|
||||
|
||||
let formatter = formatters.get(vintl)
|
||||
let formatter = formatters.get(vintl);
|
||||
|
||||
if (formatter == null) {
|
||||
const formatterRef = computed(() => createFormatter(vintl.intl))
|
||||
formatter = (value, options) => formatterRef.value(value, options)
|
||||
formatters.set(vintl, formatter)
|
||||
const formatterRef = computed(() => createFormatter(vintl.intl));
|
||||
formatter = (value, options) => formatterRef.value(value, options);
|
||||
formatters.set(vintl, formatter);
|
||||
}
|
||||
|
||||
return formatter
|
||||
return formatter;
|
||||
}
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
type ImageUploadContext = {
|
||||
projectID?: string
|
||||
context: 'project' | 'version' | 'thread_message' | 'report'
|
||||
}
|
||||
projectID?: string;
|
||||
context: "project" | "version" | "thread_message" | "report";
|
||||
};
|
||||
|
||||
interface ImageUploadResponse {
|
||||
id: string
|
||||
url: string
|
||||
id: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export const useImageUpload = async (file: File, ctx: ImageUploadContext) => {
|
||||
// Make sure file is of type image/png, image/jpeg, image/gif, or image/webp
|
||||
if (
|
||||
!file.type.startsWith('image/') ||
|
||||
!['png', 'jpeg', 'gif', 'webp'].includes(file.type.split('/')[1])
|
||||
!file.type.startsWith("image/") ||
|
||||
!["png", "jpeg", "gif", "webp"].includes(file.type.split("/")[1])
|
||||
) {
|
||||
throw new Error('File is not an accepted image type')
|
||||
throw new Error("File is not an accepted image type");
|
||||
}
|
||||
|
||||
// Make sure file is less than 1MB
|
||||
if (file.size > 1024 * 1024) {
|
||||
throw new Error('File is too large')
|
||||
throw new Error("File is too large");
|
||||
}
|
||||
|
||||
const qs = new URLSearchParams()
|
||||
if (ctx.projectID) qs.set('project_id', ctx.projectID)
|
||||
qs.set('context', ctx.context)
|
||||
qs.set('ext', file.type.split('/')[1])
|
||||
const url = `image?${qs.toString()}`
|
||||
const qs = new URLSearchParams();
|
||||
if (ctx.projectID) qs.set("project_id", ctx.projectID);
|
||||
qs.set("context", ctx.context);
|
||||
qs.set("ext", file.type.split("/")[1]);
|
||||
const url = `image?${qs.toString()}`;
|
||||
|
||||
const response = (await useBaseFetch(url, {
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
body: file,
|
||||
apiVersion: 3,
|
||||
})) as ImageUploadResponse
|
||||
})) as ImageUploadResponse;
|
||||
|
||||
// Type check to see if response has a url property and an id property
|
||||
if (!response?.id || typeof response.id !== 'string') {
|
||||
throw new Error('Unexpected response from server')
|
||||
if (!response?.id || typeof response.id !== "string") {
|
||||
throw new Error("Unexpected response from server");
|
||||
}
|
||||
if (!response?.url || typeof response.url !== 'string') {
|
||||
throw new Error('Unexpected response from server')
|
||||
if (!response?.url || typeof response.url !== "string") {
|
||||
throw new Error("Unexpected response from server");
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
export const useLoading = () => useState('loading', () => false)
|
||||
/* eslint-disable no-undef */
|
||||
export const useLoading = () => useState("loading", () => false);
|
||||
|
||||
export const startLoading = () => {
|
||||
const loading = useLoading()
|
||||
const loading = useLoading();
|
||||
|
||||
loading.value = true
|
||||
}
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
export const stopLoading = () => {
|
||||
const loading = useLoading()
|
||||
const loading = useLoading();
|
||||
|
||||
loading.value = false
|
||||
}
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
@@ -1,34 +1,37 @@
|
||||
export const useNotifications = () => useState('notifications', () => [])
|
||||
/* eslint-disable no-undef */
|
||||
export const useNotifications = () => useState("notifications", () => []);
|
||||
|
||||
export const addNotification = (notification) => {
|
||||
const notifications = useNotifications()
|
||||
const notifications = useNotifications();
|
||||
|
||||
const existingNotif = notifications.value.find(
|
||||
(x) =>
|
||||
x.text === notification.text && x.title === notification.title && x.type === notification.type
|
||||
)
|
||||
x.text === notification.text &&
|
||||
x.title === notification.title &&
|
||||
x.type === notification.type,
|
||||
);
|
||||
if (existingNotif) {
|
||||
setNotificationTimer(existingNotif)
|
||||
setNotificationTimer(existingNotif);
|
||||
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
notification.id = new Date()
|
||||
notification.id = new Date();
|
||||
|
||||
setNotificationTimer(notification)
|
||||
notifications.value.push(notification)
|
||||
}
|
||||
setNotificationTimer(notification);
|
||||
notifications.value.push(notification);
|
||||
};
|
||||
|
||||
export const setNotificationTimer = (notification) => {
|
||||
if (!notification) return
|
||||
if (!notification) return;
|
||||
|
||||
const notifications = useNotifications()
|
||||
const notifications = useNotifications();
|
||||
|
||||
if (notification.timer) {
|
||||
clearTimeout(notification.timer)
|
||||
clearTimeout(notification.timer);
|
||||
}
|
||||
|
||||
notification.timer = setTimeout(() => {
|
||||
notifications.value.splice(notifications.value.indexOf(notification), 1)
|
||||
}, 30000)
|
||||
}
|
||||
notifications.value.splice(notifications.value.indexOf(notification), 1);
|
||||
}, 30000);
|
||||
};
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { useRoute as useNativeRoute, useRouter as useNativeRouter } from 'vue-router'
|
||||
export { useRoute as useNativeRoute, useRouter as useNativeRouter } from "vue-router";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const getArrayOrString = (x) => {
|
||||
if (typeof x === 'string' || x instanceof String) {
|
||||
return [x]
|
||||
if (typeof x === "string" || x instanceof String) {
|
||||
return [x];
|
||||
} else {
|
||||
return x
|
||||
return x;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/* eslint-disable no-undef */
|
||||
/**
|
||||
* Extracts the [id] from the route params and returns it as a ref.
|
||||
*
|
||||
* @param {string?} key The key of the route param to extract.
|
||||
* @returns {import('vue').Ref<string | string[] | undefined>}
|
||||
*/
|
||||
export const useRouteId = (key = 'id') => {
|
||||
const route = useNativeRoute()
|
||||
return route.params?.[key] || undefined
|
||||
}
|
||||
export const useRouteId = (key = "id") => {
|
||||
const route = useNativeRoute();
|
||||
return route.params?.[key] || undefined;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import tags from '~/generated/state.json'
|
||||
/* eslint-disable no-undef */
|
||||
import tags from "~/generated/state.json";
|
||||
|
||||
export const useTags = () =>
|
||||
useState('tags', () => ({
|
||||
useState("tags", () => ({
|
||||
categories: tags.categories,
|
||||
loaders: tags.loaders,
|
||||
gameVersions: tags.gameVersions,
|
||||
@@ -9,56 +10,56 @@ export const useTags = () =>
|
||||
reportTypes: tags.reportTypes,
|
||||
projectTypes: [
|
||||
{
|
||||
actual: 'mod',
|
||||
id: 'mod',
|
||||
display: 'mod',
|
||||
actual: "mod",
|
||||
id: "mod",
|
||||
display: "mod",
|
||||
},
|
||||
{
|
||||
actual: 'mod',
|
||||
id: 'plugin',
|
||||
display: 'plugin',
|
||||
actual: "mod",
|
||||
id: "plugin",
|
||||
display: "plugin",
|
||||
},
|
||||
{
|
||||
actual: 'mod',
|
||||
id: 'datapack',
|
||||
display: 'data pack',
|
||||
actual: "mod",
|
||||
id: "datapack",
|
||||
display: "data pack",
|
||||
},
|
||||
{
|
||||
actual: 'shader',
|
||||
id: 'shader',
|
||||
display: 'shader',
|
||||
actual: "shader",
|
||||
id: "shader",
|
||||
display: "shader",
|
||||
},
|
||||
{
|
||||
actual: 'resourcepack',
|
||||
id: 'resourcepack',
|
||||
display: 'resource pack',
|
||||
actual: "resourcepack",
|
||||
id: "resourcepack",
|
||||
display: "resource pack",
|
||||
},
|
||||
{
|
||||
actual: 'modpack',
|
||||
id: 'modpack',
|
||||
display: 'modpack',
|
||||
actual: "modpack",
|
||||
id: "modpack",
|
||||
display: "modpack",
|
||||
},
|
||||
],
|
||||
loaderData: {
|
||||
pluginLoaders: ['bukkit', 'spigot', 'paper', 'purpur', 'sponge', 'folia'],
|
||||
pluginPlatformLoaders: ['bungeecord', 'waterfall', 'velocity'],
|
||||
pluginLoaders: ["bukkit", "spigot", "paper", "purpur", "sponge", "folia"],
|
||||
pluginPlatformLoaders: ["bungeecord", "waterfall", "velocity"],
|
||||
allPluginLoaders: [
|
||||
'bukkit',
|
||||
'spigot',
|
||||
'paper',
|
||||
'purpur',
|
||||
'sponge',
|
||||
'bungeecord',
|
||||
'waterfall',
|
||||
'velocity',
|
||||
'folia',
|
||||
"bukkit",
|
||||
"spigot",
|
||||
"paper",
|
||||
"purpur",
|
||||
"sponge",
|
||||
"bungeecord",
|
||||
"waterfall",
|
||||
"velocity",
|
||||
"folia",
|
||||
],
|
||||
dataPackLoaders: ['datapack'],
|
||||
modLoaders: ['forge', 'fabric', 'quilt', 'liteloader', 'modloader', 'rift', 'neoforge'],
|
||||
hiddenModLoaders: ['liteloader', 'modloader', 'rift'],
|
||||
dataPackLoaders: ["datapack"],
|
||||
modLoaders: ["forge", "fabric", "quilt", "liteloader", "modloader", "rift", "neoforge"],
|
||||
hiddenModLoaders: ["liteloader", "modloader", "rift"],
|
||||
},
|
||||
projectViewModes: ['list', 'grid', 'gallery'],
|
||||
approvedStatuses: ['approved', 'archived', 'unlisted', 'private'],
|
||||
rejectedStatuses: ['rejected', 'withheld'],
|
||||
staffRoles: ['moderator', 'admin'],
|
||||
}))
|
||||
projectViewModes: ["list", "grid", "gallery"],
|
||||
approvedStatuses: ["approved", "archived", "unlisted", "private"],
|
||||
rejectedStatuses: ["rejected", "withheld"],
|
||||
staffRoles: ["moderator", "admin"],
|
||||
}));
|
||||
|
||||
@@ -1,58 +1,59 @@
|
||||
/* eslint-disable no-undef */
|
||||
export const useTheme = () =>
|
||||
useState('theme', () => {
|
||||
const colorMode = useCookie('color-mode', {
|
||||
useState("theme", () => {
|
||||
const colorMode = useCookie("color-mode", {
|
||||
maxAge: 60 * 60 * 24 * 365 * 10,
|
||||
sameSite: 'lax',
|
||||
sameSite: "lax",
|
||||
secure: true,
|
||||
httpOnly: false,
|
||||
path: '/',
|
||||
})
|
||||
path: "/",
|
||||
});
|
||||
|
||||
if (!colorMode.value) {
|
||||
colorMode.value = {
|
||||
value: 'dark',
|
||||
preference: 'system',
|
||||
}
|
||||
value: "dark",
|
||||
preference: "system",
|
||||
};
|
||||
}
|
||||
|
||||
if (colorMode.value.preference !== 'system') {
|
||||
colorMode.value.value = colorMode.value.preference
|
||||
if (colorMode.value.preference !== "system") {
|
||||
colorMode.value.value = colorMode.value.preference;
|
||||
}
|
||||
|
||||
return colorMode.value
|
||||
})
|
||||
return colorMode.value;
|
||||
});
|
||||
|
||||
export const updateTheme = (value, updatePreference = false) => {
|
||||
const theme = useTheme()
|
||||
const cosmetics = useCosmetics()
|
||||
const theme = useTheme();
|
||||
const cosmetics = useCosmetics();
|
||||
|
||||
const themeCookie = useCookie('color-mode', {
|
||||
const themeCookie = useCookie("color-mode", {
|
||||
maxAge: 60 * 60 * 24 * 365 * 10,
|
||||
sameSite: 'lax',
|
||||
sameSite: "lax",
|
||||
secure: true,
|
||||
httpOnly: false,
|
||||
path: '/',
|
||||
})
|
||||
path: "/",
|
||||
});
|
||||
|
||||
if (value === 'system') {
|
||||
theme.value.preference = 'system'
|
||||
if (value === "system") {
|
||||
theme.value.preference = "system";
|
||||
|
||||
const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: light)')
|
||||
const colorSchemeQueryList = window.matchMedia("(prefers-color-scheme: light)");
|
||||
if (colorSchemeQueryList.matches) {
|
||||
theme.value.value = 'light'
|
||||
theme.value.value = "light";
|
||||
} else {
|
||||
theme.value.value = cosmetics.value.preferredDarkTheme
|
||||
theme.value.value = cosmetics.value.preferredDarkTheme;
|
||||
}
|
||||
} else {
|
||||
theme.value.value = value
|
||||
if (updatePreference) theme.value.preference = value
|
||||
theme.value.value = value;
|
||||
if (updatePreference) theme.value.preference = value;
|
||||
}
|
||||
|
||||
if (process.client) {
|
||||
document.documentElement.className = `${theme.value.value}-mode`
|
||||
document.documentElement.className = `${theme.value.value}-mode`;
|
||||
}
|
||||
|
||||
themeCookie.value = theme.value
|
||||
}
|
||||
themeCookie.value = theme.value;
|
||||
};
|
||||
|
||||
export const DARK_THEMES = ['dark', 'oled', 'retro']
|
||||
export const DARK_THEMES = ["dark", "oled", "retro"];
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
type AsyncFunction<TArgs extends any[], TResult> = (...args: TArgs) => Promise<TResult>
|
||||
type ErrorFunction = (err: any) => void | Promise<void>
|
||||
type VoidFunction = () => void | Promise<void>
|
||||
type AsyncFunction<TArgs extends any[], TResult> = (...args: TArgs) => Promise<TResult>;
|
||||
type ErrorFunction = (err: any) => void | Promise<void>;
|
||||
type VoidFunction = () => void | Promise<void>;
|
||||
|
||||
type useClientTry = <TArgs extends any[], TResult>(
|
||||
fn: AsyncFunction<TArgs, TResult>,
|
||||
onFail?: ErrorFunction,
|
||||
onFinish?: VoidFunction
|
||||
) => (...args: TArgs) => Promise<TResult | undefined>
|
||||
onFinish?: VoidFunction,
|
||||
) => (...args: TArgs) => Promise<TResult | undefined>;
|
||||
|
||||
const defaultOnError: ErrorFunction = (error) => {
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
text: error?.data?.description || error.message || error || 'Unknown error',
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
group: "main",
|
||||
title: "An error occurred",
|
||||
text: error?.data?.description || error.message || error || "Unknown error",
|
||||
type: "error",
|
||||
});
|
||||
};
|
||||
|
||||
export const useClientTry: useClientTry =
|
||||
(fn, onFail = defaultOnError, onFinish) =>
|
||||
async (...args) => {
|
||||
startLoading()
|
||||
startLoading();
|
||||
try {
|
||||
return await fn(...args)
|
||||
return await fn(...args);
|
||||
} catch (err) {
|
||||
if (onFail) {
|
||||
await onFail(err)
|
||||
await onFail(err);
|
||||
} else {
|
||||
console.error('[CLIENT TRY ERROR]', err)
|
||||
console.error("[CLIENT TRY ERROR]", err);
|
||||
}
|
||||
} finally {
|
||||
if (onFinish) await onFinish()
|
||||
stopLoading()
|
||||
if (onFinish) await onFinish();
|
||||
stopLoading();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,173 +1,176 @@
|
||||
/* eslint-disable no-undef */
|
||||
export const useUser = async (force = false) => {
|
||||
const user = useState('user', () => {})
|
||||
const user = useState("user", () => {});
|
||||
|
||||
if (!user.value || force || (user.value && Date.now() - user.value.lastUpdated > 300000)) {
|
||||
user.value = await initUser()
|
||||
user.value = await initUser();
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
return user;
|
||||
};
|
||||
|
||||
export const initUser = async () => {
|
||||
const auth = (await useAuth()).value
|
||||
const auth = (await useAuth()).value;
|
||||
|
||||
const user = {
|
||||
notifications: [],
|
||||
follows: [],
|
||||
lastUpdated: 0,
|
||||
}
|
||||
};
|
||||
|
||||
if (auth.user && auth.user.id) {
|
||||
try {
|
||||
const [follows, collections] = await Promise.all([
|
||||
useBaseFetch(`user/${auth.user.id}/follows`),
|
||||
useBaseFetch(`user/${auth.user.id}/collections`, { apiVersion: 3 }),
|
||||
])
|
||||
]);
|
||||
|
||||
user.collections = collections
|
||||
user.follows = follows
|
||||
user.lastUpdated = Date.now()
|
||||
user.collections = collections;
|
||||
user.follows = follows;
|
||||
user.lastUpdated = Date.now();
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
return user;
|
||||
};
|
||||
|
||||
export const initUserCollections = async () => {
|
||||
const auth = (await useAuth()).value
|
||||
const user = (await useUser()).value
|
||||
const auth = (await useAuth()).value;
|
||||
const user = (await useUser()).value;
|
||||
|
||||
if (auth.user && auth.user.id) {
|
||||
try {
|
||||
user.collections = await useBaseFetch(`user/${auth.user.id}/collections`, { apiVersion: 3 })
|
||||
user.collections = await useBaseFetch(`user/${auth.user.id}/collections`, { apiVersion: 3 });
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const initUserFollows = async () => {
|
||||
const auth = (await useAuth()).value
|
||||
const user = (await useUser()).value
|
||||
const auth = (await useAuth()).value;
|
||||
const user = (await useUser()).value;
|
||||
|
||||
if (auth.user && auth.user.id) {
|
||||
try {
|
||||
user.follows = await useBaseFetch(`user/${auth.user.id}/follows`)
|
||||
user.follows = await useBaseFetch(`user/${auth.user.id}/follows`);
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const initUserProjects = async () => {
|
||||
const auth = (await useAuth()).value
|
||||
const user = (await useUser()).value
|
||||
const auth = (await useAuth()).value;
|
||||
const user = (await useUser()).value;
|
||||
|
||||
if (auth.user && auth.user.id) {
|
||||
try {
|
||||
user.projects = await useBaseFetch(`user/${auth.user.id}/projects`)
|
||||
user.projects = await useBaseFetch(`user/${auth.user.id}/projects`);
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const userCollectProject = async (collection, projectId) => {
|
||||
const user = (await useUser()).value
|
||||
await initUserCollections()
|
||||
const user = (await useUser()).value;
|
||||
await initUserCollections();
|
||||
|
||||
const collectionId = collection.id
|
||||
const collectionId = collection.id;
|
||||
|
||||
const latestCollection = user.collections.find((x) => x.id === collectionId)
|
||||
const latestCollection = user.collections.find((x) => x.id === collectionId);
|
||||
if (!latestCollection) {
|
||||
throw new Error('This collection was not found. Has it been deleted?')
|
||||
throw new Error("This collection was not found. Has it been deleted?");
|
||||
}
|
||||
|
||||
const add = !latestCollection.projects.includes(projectId)
|
||||
const add = !latestCollection.projects.includes(projectId);
|
||||
const projects = add
|
||||
? [...latestCollection.projects, projectId]
|
||||
: [...latestCollection.projects].filter((x) => x !== projectId)
|
||||
: [...latestCollection.projects].filter((x) => x !== projectId);
|
||||
|
||||
const idx = user.collections.findIndex((x) => x.id === latestCollection.id)
|
||||
const idx = user.collections.findIndex((x) => x.id === latestCollection.id);
|
||||
if (idx >= 0) {
|
||||
user.collections[idx].projects = projects
|
||||
user.collections[idx].projects = projects;
|
||||
}
|
||||
|
||||
await useBaseFetch(`collection/${collection.id}`, {
|
||||
method: 'PATCH',
|
||||
method: "PATCH",
|
||||
body: {
|
||||
new_projects: projects,
|
||||
},
|
||||
apiVersion: 3,
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const userFollowProject = async (project) => {
|
||||
const user = (await useUser()).value
|
||||
const user = (await useUser()).value;
|
||||
|
||||
user.follows = user.follows.concat(project)
|
||||
project.followers++
|
||||
user.follows = user.follows.concat(project);
|
||||
project.followers++;
|
||||
|
||||
setTimeout(() => {
|
||||
useBaseFetch(`project/${project.id}/follow`, {
|
||||
method: 'POST',
|
||||
})
|
||||
})
|
||||
}
|
||||
method: "POST",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const userUnfollowProject = async (project) => {
|
||||
const user = (await useUser()).value
|
||||
const user = (await useUser()).value;
|
||||
|
||||
user.follows = user.follows.filter((x) => x.id !== project.id)
|
||||
project.followers--
|
||||
user.follows = user.follows.filter((x) => x.id !== project.id);
|
||||
project.followers--;
|
||||
|
||||
setTimeout(() => {
|
||||
useBaseFetch(`project/${project.id}/follow`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
})
|
||||
}
|
||||
method: "DELETE",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const resendVerifyEmail = async () => {
|
||||
const app = useNuxtApp()
|
||||
const app = useNuxtApp();
|
||||
|
||||
startLoading()
|
||||
startLoading();
|
||||
try {
|
||||
await useBaseFetch('auth/email/resend_verify', {
|
||||
method: 'POST',
|
||||
})
|
||||
await useBaseFetch("auth/email/resend_verify", {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
const auth = await useAuth()
|
||||
const auth = await useAuth();
|
||||
app.$notify({
|
||||
group: 'main',
|
||||
title: 'Email sent',
|
||||
group: "main",
|
||||
title: "Email sent",
|
||||
text: `An email with a link to verify your account has been sent to ${auth.value.user.email}.`,
|
||||
type: 'success',
|
||||
})
|
||||
type: "success",
|
||||
});
|
||||
} catch (err) {
|
||||
app.$notify({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
group: "main",
|
||||
title: "An error occurred",
|
||||
text: err.data.description,
|
||||
type: 'error',
|
||||
})
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
stopLoading()
|
||||
}
|
||||
stopLoading();
|
||||
};
|
||||
|
||||
export const logout = async () => {
|
||||
startLoading()
|
||||
const auth = await useAuth()
|
||||
startLoading();
|
||||
const auth = await useAuth();
|
||||
try {
|
||||
await useBaseFetch(`session/${auth.value.token}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
} catch {}
|
||||
method: "DELETE",
|
||||
});
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
await useAuth('none')
|
||||
useCookie('auth-token').value = null
|
||||
await navigateTo('/')
|
||||
stopLoading()
|
||||
}
|
||||
await useAuth("none");
|
||||
useCookie("auth-token").value = null;
|
||||
await navigateTo("/");
|
||||
stopLoading();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user