format & lint

This commit is contained in:
ppom 2024-03-04 12:00:00 +01:00
parent 9c694c6aac
commit c4550354c3
15 changed files with 165 additions and 130 deletions

View File

@ -5,7 +5,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Admin do
import Mobilizon.Users.Guards
alias Mobilizon.{Actors, Admin, Config, Events, Instances, Users, Media}
alias Mobilizon.{Actors, Admin, Config, Events, Instances, Media, Users}
alias Mobilizon.Actors.{Actor, Follower}
alias Mobilizon.Admin.{ActionLog, Setting, SettingMedia}
alias Mobilizon.Cldr.Language

View File

@ -128,10 +128,12 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
description: "The instance's logo",
resolve: &Admin.get_instance_logo/3
)
field(:instance_favicon, :media,
description: "The instance's favicon",
resolve: &Admin.get_instance_favicon/3
)
field(:default_picture, :media,
description: "The default picture",
resolve: &Admin.get_default_picture/3
@ -433,10 +435,12 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
description:
"The instance's logo, either as an object or directly the ID of an existing media"
)
arg(:instance_favicon, :media_input,
description:
"The instance's favicon, either as an object or directly the ID of an existing media"
)
arg(:default_picture, :media_input,
description:
"The default picture, either as an object or directly the ID of an existing media"

View File

@ -79,19 +79,19 @@ defmodule Mobilizon.Config do
def instance_slogan, do: config_cached_value("instance", "instance_slogan")
@spec instance_logo :: Media.t() | nil
def instance_logo, do: config_cached_value( "instance", "instance_logo")
def instance_logo, do: config_cached_value("instance", "instance_logo")
@spec instance_favicon :: Media.t() | nil
def instance_favicon, do: config_cached_value( "instance", "instance_favicon")
def instance_favicon, do: config_cached_value("instance", "instance_favicon")
@spec default_picture :: Media.t() | nil
def default_picture, do: config_cached_value( "instance", "default_picture")
def default_picture, do: config_cached_value("instance", "default_picture")
@spec primary_color :: Media.t() | nil
def primary_color, do: config_cached_value( "instance", "primary_color")
def primary_color, do: config_cached_value("instance", "primary_color")
@spec secondary_color :: Media.t() | nil
def secondary_color, do: config_cached_value( "instance", "secondary_color")
def secondary_color, do: config_cached_value("instance", "secondary_color")
@spec contact :: String.t() | nil
def contact, do: config_cached_value("instance", "contact")

View File

@ -6,30 +6,36 @@ defmodule Mobilizon.Web.ManifestController do
@spec manifest(Plug.Conn.t(), any) :: Plug.Conn.t()
def manifest(conn, _params) do
favicons = case Config.instance_favicon() do
%Media{file: %{url: url}, metadata: metadata} ->
[Map.merge(
%{
src: url,
},
case metadata do
%{width: width} -> %{sizes: "#{width}x#{width}"}
_ -> %{}
end
)]
_ -> [
%{
src: "./img/icons/android-chrome-512x512.png",
sizes: "512x512",
type: "image/png"
},
%{
src: "./img/icons/android-chrome-192x192.png",
sizes: "192x192",
type: "image/png"
}
]
end
favicons =
case Config.instance_favicon() do
%Media{file: %{url: url}, metadata: metadata} ->
[
Map.merge(
%{
src: url
},
case metadata do
%{width: width} -> %{sizes: "#{width}x#{width}"}
_ -> %{}
end
)
]
_ ->
[
%{
src: "./img/icons/android-chrome-512x512.png",
sizes: "512x512",
type: "image/png"
},
%{
src: "./img/icons/android-chrome-192x192.png",
sizes: "192x192",
type: "image/png"
}
]
end
json(conn, %{
name: Config.instance_name(),
start_url: "/",

View File

@ -18,8 +18,7 @@ defmodule Mobilizon.Web do
"""
def static_paths,
do:
~w(index.html service-worker.js css fonts img js robots.txt assets)
do: ~w(index.html service-worker.js css fonts img js robots.txt assets)
def controller do
quote do

View File

@ -1,40 +1,38 @@
<!DOCTYPE html>
<html lang={Map.get(assigns, :locale, "en" )} dir={language_direction(assigns)}>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="apple-touch-icon" href={favicon_url()} sizes={favicon_sizes()} />
<link rel="icon" href={favicon_url()} sizes={favicon_sizes()} />
<link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color={theme_color()} />
<link rel="manifest" href="/manifest.webmanifest" />
<meta name="theme-color" content={theme_color()} />
<script>
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
</script>
<%= if root?(assigns) do %>
<link rel="preload" href="/img/shape-1.svg" as="image" />
<link rel="preload" href="/img/shape-2.svg" as="image" />
<link rel="preload" href="/img/shape-3.svg" as="image" />
<% end %>
<%= tags(assigns) || assigns.tags %>
<%= Vite.vite_client() %>
<%= Vite.vite_snippet("src/main.ts") %>
</head>
<body>
<noscript>
<strong>
We're sorry but Mobilizon doesn't work properly without JavaScript enabled. Please enable it to continue.
</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
<html lang={Map.get(assigns, :locale, "en")} dir={language_direction(assigns)}>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="apple-touch-icon" href={favicon_url()} sizes={favicon_sizes()} />
<link rel="icon" href={favicon_url()} sizes={favicon_sizes()} />
<link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color={theme_color()} />
<link rel="manifest" href="/manifest.webmanifest" />
<meta name="theme-color" content={theme_color()} />
<script>
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
</script>
<%= if root?(assigns) do %>
<link rel="preload" href="/img/shape-1.svg" as="image" />
<link rel="preload" href="/img/shape-2.svg" as="image" />
<link rel="preload" href="/img/shape-3.svg" as="image" />
<% end %>
<%= tags(assigns) || assigns.tags %>
<%= Vite.vite_client() %>
<%= Vite.vite_snippet("src/main.ts") %>
</head>
<body>
<noscript>
<strong>
We're sorry but Mobilizon doesn't work properly without JavaScript enabled. Please enable it to continue.
</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -95,17 +95,21 @@ defmodule Mobilizon.Web.PageView do
defp favicon do
case Config.instance_favicon() do
%{file: %{url: url}, metadata: metadata} -> %{
%{file: %{url: url}, metadata: metadata} ->
%{
src: url,
sizes: case metadata do
%{width: width} -> "#{width}x#{width}"
_ -> "any"
end
}
_ -> %{
sizes:
case metadata do
%{width: width} -> "#{width}x#{width}"
_ -> "any"
end
}
_ ->
%{
src: "/img/icons/apple-touch-icon-152x152.png",
sizes: "152x152"
}
}
end
end

View File

@ -31,16 +31,10 @@
/>
</g>
</svg>
<img
v-else
alt=""
class="max-h-12 w-auto"
:src="instanceLogoUrl"
/>
<img v-else alt="" class="max-h-12 w-auto" :src="instanceLogoUrl" />
</template>
<script lang="ts" setup>
import { watch } from "vue";
import { useInstanceLogoUrl } from "@/composition/apollo/config";
const { instanceLogoUrl } = useInstanceLogoUrl();

View File

@ -3,9 +3,7 @@
class="bg-white border-gray-200 px-2 sm:px-4 py-2.5 dark:bg-zinc-900"
id="navbar"
>
<div
class="container mx-auto flex flex-wrap items-center gap-2 sm:gap-4"
>
<div class="container mx-auto flex flex-wrap items-center gap-2 sm:gap-4">
<router-link
:to="{ name: RouteName.HOME }"
class="flex items-center"

View File

@ -95,12 +95,8 @@ export function useColors() {
config: Pick<IConfig, "primaryColor" | "secondaryColor">;
}>(COLORS);
const primaryColor = computed(
() => result.value?.config?.primaryColor
);
const secondaryColor = computed(
() => result.value?.config?.secondaryColor
);
const primaryColor = computed(() => result.value?.config?.primaryColor);
const secondaryColor = computed(() => result.value?.config?.secondaryColor);
return { primaryColor, secondaryColor, error, loading };
}
@ -109,9 +105,7 @@ export function useDefaultPicture() {
config: Pick<IConfig, "defaultPicture">;
}>(DEFAULT_PICTURE);
const defaultPicture = computed(
() => result.value?.config?.defaultPicture
);
const defaultPicture = computed(() => result.value?.config?.defaultPicture);
return { defaultPicture, error, loading };
}

View File

@ -60,11 +60,17 @@ apolloClient
const primaryColor = configData.config?.primaryColor;
if (primaryColor) {
document.documentElement.style.setProperty('--custom-primary', primaryColor);
document.documentElement.style.setProperty(
"--custom-primary",
primaryColor
);
}
const secondaryColor = configData.config?.secondaryColor;
if (secondaryColor) {
document.documentElement.style.setProperty('--custom-secondary', secondaryColor);
document.documentElement.style.setProperty(
"--custom-secondary",
secondaryColor
);
}
});

View File

@ -25,7 +25,7 @@ export interface IMediaMetadata {
}
export interface IModifiableMedia {
file: Ref<File | null>
firstHash: string | null
hash: string | null
file: Ref<File | null>;
firstHash: string | null;
hash: string | null;
}

View File

@ -5,15 +5,18 @@ import { apolloClient } from "@/vue-apollo";
import { IConfig } from "@/types/config.model";
import { ABOUT } from "@/graphql/config";
const { result } = provideApolloClient(apolloClient)(() => useQuery<{config: Pick<IConfig, "name">;
}>(ABOUT));
const { result } = provideApolloClient(apolloClient)(() =>
useQuery<{ config: Pick<IConfig, "name"> }>(ABOUT)
);
const instanceName = computed(() => result.value?.config?.name);
export function useHead(args: any) {
return unHead({
...args,
title: computed(() => args?.title?.value
? `${args.title.value} - ${instanceName.value}`
: instanceName.value)
title: computed(() =>
args?.title?.value
? `${args.title.value} - ${instanceName.value}`
: instanceName.value
),
});
}

View File

@ -30,9 +30,7 @@ export function buildFileVariable(
};
}
export function readFileAsync(
file: File
): Promise<ArrayBuffer | null> {
export function readFileAsync(file: File): Promise<ArrayBuffer | null> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
@ -50,7 +48,11 @@ export async function fileHash(file: File): Promise<string | null> {
const data = await readFileAsync(file);
if (data === null) return null;
const hash = await crypto.subtle.digest("SHA-1", data);
const b64Hash = btoa(Array.from(new Uint8Array(hash)).map(b => String.fromCharCode(b)).join(''))
const b64Hash = btoa(
Array.from(new Uint8Array(hash))
.map((b) => String.fromCharCode(b))
.join("")
);
return b64Hash;
}
@ -62,7 +64,10 @@ export function initWrappedMedia(): IModifiableMedia {
};
}
export async function loadWrappedMedia(modifiableMedia: IModifiableMedia, media: IMedia | null) {
export async function loadWrappedMedia(
modifiableMedia: IModifiableMedia,
media: IMedia | null
) {
watch(modifiableMedia.file, async () => {
if (modifiableMedia.file.value) {
modifiableMedia.hash = await fileHash(modifiableMedia.file.value);
@ -80,8 +85,12 @@ export async function loadWrappedMedia(modifiableMedia: IModifiableMedia, media:
}
}
export function asMediaInput(mmedia: IModifiableMedia, name: string, fallbackId: number): any {
let ret = {
export function asMediaInput(
mmedia: IModifiableMedia,
name: string,
fallbackId: number
): any {
const ret = {
[name]: {},
};
if (mmedia.file.value) {
@ -95,7 +104,7 @@ export function asMediaInput(mmedia: IModifiableMedia, name: string, fallbackId:
};
} else {
ret[name] = {
mediaId: fallbackId
mediaId: fallbackId,
};
}
}

View File

@ -61,7 +61,11 @@
<label class="field flex flex-col">
<p>{{ t("Logo") }}</p>
<small>
{{ t("Logo of the instance. Defaults to the upstream Mobilizon logo.") }}
{{
t(
"Logo of the instance. Defaults to the upstream Mobilizon logo."
)
}}
</small>
<picture-upload
v-model:modelValue="instanceLogoFile"
@ -73,7 +77,11 @@
<label class="field flex flex-col">
<p>{{ t("Favicon") }}</p>
<small>
{{ t("Browser tab icon and PWA icon of the instance. Defaults to the upstream Mobilizon icon.") }}
{{
t(
"Browser tab icon and PWA icon of the instance. Defaults to the upstream Mobilizon icon."
)
}}
</small>
<picture-upload
v-model:modelValue="instanceFaviconFile"
@ -95,9 +103,7 @@
/>
</label>
<div class="field flex flex-col">
<label class="" for="primary-color">{{
t("Primary Color")
}}</label>
<label class="" for="primary-color">{{ t("Primary Color") }}</label>
<o-input
type="color"
v-model="settingsToWrite.primaryColor"
@ -450,7 +456,11 @@ import type { Notifier } from "@/plugins/notifier";
// Media upload related
import PictureUpload from "@/components/PictureUpload.vue";
import { initWrappedMedia, loadWrappedMedia, asMediaInput } from "@/utils/image";
import {
initWrappedMedia,
loadWrappedMedia,
asMediaInput,
} from "@/utils/image";
import { useDefaultMaxSize } from "@/composition/config";
const defaultAdminSettings: IAdminSettings = {
@ -475,10 +485,7 @@ const defaultAdminSettings: IAdminSettings = {
instanceLanguages: [],
};
const {
result: adminSettingsResult,
onResult: onAdminSettingsResult
} = useQuery<{
const { onResult: onAdminSettingsResult } = useQuery<{
adminSettings: IAdminSettings;
}>(ADMIN_SETTINGS);
@ -486,9 +493,10 @@ const adminSettings = ref<IAdminSettings>();
onAdminSettingsResult(async ({ data }) => {
if (!data) return;
adminSettings.value = {
...data.adminSettings,
} ?? defaultAdminSettings;
adminSettings.value =
{
...data.adminSettings,
} ?? defaultAdminSettings;
loadWrappedMedia(instanceLogo, adminSettings.value.instanceLogo);
loadWrappedMedia(instanceFavicon, adminSettings.value.instanceFavicon);
@ -563,9 +571,21 @@ saveAdminSettingsError((e) => {
const updateSettings = async (): Promise<void> => {
const variables = {
...settingsToWrite.value,
...asMediaInput(instanceLogo, "instanceLogo", adminSettings.value?.instanceLogo?.id),
...asMediaInput(instanceFavicon, "instanceFavicon", adminSettings.value?.instanceFavicon?.id),
...asMediaInput(defaultPicture, "defaultPicture", adminSettings.value?.defaultPicture?.id),
...asMediaInput(
instanceLogo,
"instanceLogo",
adminSettings.value?.instanceLogo?.id
),
...asMediaInput(
instanceFavicon,
"instanceFavicon",
adminSettings.value?.instanceFavicon?.id
),
...asMediaInput(
defaultPicture,
"defaultPicture",
adminSettings.value?.defaultPicture?.id
),
};
saveAdminSettings(variables);
};