Add app icons across web, Android, and the desktop app
- Web: favicon.ico + png icons under static/, served from the site root and linked from every page head. - Android: the artwork becomes the launcher icon — the 432px adaptive foreground over the gruvbox background, replacing the placeholder vector drawables. - Desktop: the icon is the Qt window/taskbar icon (embedded via app.qrc), and the app is now an installable package — a wrapped binary, a photog.desktop entry, and hicolor icons — so `nix profile install ./desktop` puts "Photog" in the application menu.
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#1d2021"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
</vector>
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Aperture blades in Gruvbox aqua on the adaptive-icon 108dp canvas.
|
||||
The safe zone is the middle 72dp, so the art is inset accordingly. -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
|
||||
<path
|
||||
android:fillColor="#8ec07c"
|
||||
android:pathData="M54,30 A24,24 0 0,1 78,54 L54,54 Z" />
|
||||
<path
|
||||
android:fillColor="#689d6a"
|
||||
android:pathData="M78,54 A24,24 0 0,1 54,78 L54,54 Z" />
|
||||
<path
|
||||
android:fillColor="#8ec07c"
|
||||
android:pathData="M54,78 A24,24 0 0,1 30,54 L54,54 Z" />
|
||||
<path
|
||||
android:fillColor="#689d6a"
|
||||
android:pathData="M30,54 A24,24 0 0,1 54,30 L54,54 Z" />
|
||||
|
||||
<path
|
||||
android:strokeColor="#ebdbb2"
|
||||
android:strokeWidth="3"
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M54,28 A26,26 0 1,1 53.99,28 Z" />
|
||||
</vector>
|
||||
@@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- minSdk is 28, so every device resolves the v26 adaptive icon and no
|
||||
density-bucket PNG fallbacks are needed. -->
|
||||
density-bucket PNG fallbacks are needed. The foreground is the full circular
|
||||
app icon (ic_launcher_foreground.png); the launcher mask crops the disc to
|
||||
its shape, and the solid gruvbox background fills the transparent corners. -->
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<background android:drawable="@color/gruvbox_bg" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<background android:drawable="@color/gruvbox_bg" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
||||
|
After Width: | Height: | Size: 87 KiB |
@@ -4,6 +4,7 @@ project(photogallery_uploader LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Network Concurrent)
|
||||
find_package(Qt6Keychain REQUIRED)
|
||||
@@ -15,6 +16,7 @@ add_executable(uploader
|
||||
settings.cpp
|
||||
uploadclient.cpp
|
||||
imageprep.cpp
|
||||
app.qrc
|
||||
)
|
||||
|
||||
target_link_libraries(uploader PRIVATE
|
||||
@@ -23,3 +25,14 @@ target_link_libraries(uploader PRIVATE
|
||||
Qt6::Concurrent
|
||||
Qt6Keychain::Qt6Keychain
|
||||
)
|
||||
|
||||
# Installation — the binary, a desktop entry, and the app icon in the hicolor
|
||||
# theme, so `nix profile install ./desktop` puts "Photog" in the app menu.
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS uploader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(FILES photog.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
|
||||
foreach(sz 32 128 256 512)
|
||||
install(FILES icons/app-${sz}.png
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${sz}x${sz}/apps
|
||||
RENAME photog.png)
|
||||
endforeach()
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE RCC>
|
||||
<RCC version="1.0">
|
||||
<qresource prefix="/">
|
||||
<file>icons/app-32.png</file>
|
||||
<file>icons/app-128.png</file>
|
||||
<file>icons/app-256.png</file>
|
||||
<file>icons/app-512.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -17,6 +17,28 @@
|
||||
pkgs.qt6.qtimageformats
|
||||
];
|
||||
in {
|
||||
# Installable build: `nix profile install ./desktop` drops "Photog" into
|
||||
# the application menu with its icon. wrapQtAppsHook wraps the binary so
|
||||
# it finds the Qt platform (xcb + wayland) and image-format plugins on
|
||||
# its own, without the dev shell.
|
||||
packages.default = pkgs.stdenv.mkDerivation {
|
||||
pname = "photog";
|
||||
version = "0.1.0";
|
||||
src = ./.;
|
||||
nativeBuildInputs = with pkgs; [
|
||||
cmake
|
||||
ninja
|
||||
pkg-config
|
||||
qt6.wrapQtAppsHook
|
||||
];
|
||||
buildInputs = with pkgs; [
|
||||
qt6.qtbase
|
||||
qt6.qtwayland
|
||||
qt6.qtimageformats
|
||||
qt6Packages.qtkeychain
|
||||
];
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
cmake
|
||||
|
||||
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 97 KiB |
@@ -1,4 +1,5 @@
|
||||
#include <QApplication>
|
||||
#include <QIcon>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
@@ -8,6 +9,15 @@ int main(int argc, char **argv)
|
||||
app.setApplicationName(QStringLiteral("photogallery-uploader"));
|
||||
app.setOrganizationName(QStringLiteral("inflo.ws"));
|
||||
|
||||
// Window / taskbar / alt-tab icon, embedded via app.qrc. Several sizes so
|
||||
// the small titlebar rendering stays crisp rather than downscaling 512px.
|
||||
QIcon icon;
|
||||
icon.addFile(QStringLiteral(":/icons/app-32.png"));
|
||||
icon.addFile(QStringLiteral(":/icons/app-128.png"));
|
||||
icon.addFile(QStringLiteral(":/icons/app-256.png"));
|
||||
icon.addFile(QStringLiteral(":/icons/app-512.png"));
|
||||
app.setWindowIcon(icon);
|
||||
|
||||
MainWindow window;
|
||||
window.resize(440, 680);
|
||||
window.show();
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Photog
|
||||
GenericName=Photo Uploader
|
||||
Comment=Upload photos to your gallery
|
||||
Exec=uploader
|
||||
Icon=photog
|
||||
Terminal=false
|
||||
Categories=Graphics;Photography;Network;
|
||||
@@ -713,6 +713,14 @@ func (g *Generator) copyStatic() error {
|
||||
if err := os.WriteFile(dst, data, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Also serve the favicon from the site root, where browsers and
|
||||
// crawlers request /favicon.ico by default without a <link> tag.
|
||||
if e.Name() == "favicon.ico" {
|
||||
if err := os.WriteFile(filepath.Join(g.outputDir, e.Name()), data, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 96 KiB |
@@ -6,6 +6,9 @@
|
||||
<title>{{.Date}} · Photo Gallery</title>
|
||||
<link rel="stylesheet" href="{{.FontsURL}}">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<link rel="icon" href="/static/favicon.ico" sizes="any">
|
||||
<link rel="icon" type="image/png" href="/static/web-32.png" sizes="32x32">
|
||||
<link rel="apple-touch-icon" href="/static/web-192.png">
|
||||
<style>:root { --serif: '{{.SerifFamily}}', Georgia, serif; --mj: '{{.MlFamily}}', sans-serif; }</style>
|
||||
<link rel="alternate" type="application/atom+xml" href="/feed.xml" title="Photo Feed">
|
||||
</head>
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<title>Photo Gallery</title>
|
||||
<link rel="stylesheet" href="{{.FontsURL}}">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<link rel="icon" href="/static/favicon.ico" sizes="any">
|
||||
<link rel="icon" type="image/png" href="/static/web-32.png" sizes="32x32">
|
||||
<link rel="apple-touch-icon" href="/static/web-192.png">
|
||||
<style>:root { --serif: '{{.SerifFamily}}', Georgia, serif; --mj: '{{.MlFamily}}', sans-serif; }</style>
|
||||
<link rel="alternate" type="application/atom+xml" href="/feed.xml" title="Photo Feed">
|
||||
</head>
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
<link rel="stylesheet" href="{{.FontsURL}}">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<link rel="icon" href="/static/favicon.ico" sizes="any">
|
||||
<link rel="icon" type="image/png" href="/static/web-32.png" sizes="32x32">
|
||||
<link rel="apple-touch-icon" href="/static/web-192.png">
|
||||
<style>:root { --serif: '{{.SerifFamily}}', Georgia, serif; --mj: '{{.MlFamily}}', sans-serif; }</style>
|
||||
<link rel="alternate" type="application/atom+xml" href="/feed.xml" title="Photo Feed">
|
||||
{{if .Newer}}<link rel="prefetch" href="/photo/{{.Newer.Slug}}/">
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<title>Photo Gallery</title>
|
||||
<link rel="stylesheet" href="{{.FontsURL}}">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<link rel="icon" href="/static/favicon.ico" sizes="any">
|
||||
<link rel="icon" type="image/png" href="/static/web-32.png" sizes="32x32">
|
||||
<link rel="apple-touch-icon" href="/static/web-192.png">
|
||||
<style>:root { --serif: '{{.SerifFamily}}', Georgia, serif; --mj: '{{.MlFamily}}', sans-serif; }</style>
|
||||
<link rel="alternate" type="application/atom+xml" href="/feed.xml" title="Photo Feed">
|
||||
</head>
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<title>Upload — Photo Gallery</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Crimson+Pro:ital,wght@0,400;0,600;0,700;1,400&family=Manjari:wght@100;400;700&display=swap">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<link rel="icon" href="/static/favicon.ico" sizes="any">
|
||||
<link rel="icon" type="image/png" href="/static/web-32.png" sizes="32x32">
|
||||
<link rel="apple-touch-icon" href="/static/web-192.png">
|
||||
<style>
|
||||
.upload-page {
|
||||
max-width: 520px;
|
||||
|
||||