Compare commits

..

1 Commits

Author SHA1 Message Date
Jay
acf978c302 docs-ios 2025-03-12 12:17:47 +05:30
586 changed files with 9741 additions and 17700 deletions

View File

@@ -32,8 +32,8 @@ env:
FLUTTER_VERSION: "3.24.3"
jobs:
build-linux-latest:
runs-on: ubuntu-latest
build-ubuntu:
runs-on: ubuntu-20.04
defaults:
run:
@@ -90,31 +90,22 @@ jobs:
- name: Install dependencies for desktop build
run: |
sudo apt-get update -y
sudo apt-get install -y libsecret-1-dev libsodium-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config rpm patchelf libsqlite3-dev locate libayatana-appindicator3-dev libffi-dev libtiff6 xz-utils libarchive-tools libcurl4-openssl-dev
sudo apt-get install -y libsecret-1-dev libsodium-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config libsqlite3-dev locate appindicator3-0.1 libappindicator3-dev libffi-dev libtiff5
sudo updatedb --localpaths='/usr/lib/x86_64-linux-gnu'
- name: Install appimagetool
run: |
wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x appimagetool
mv appimagetool /usr/local/bin/
- name: Build desktop app
run: |
flutter config --enable-linux-desktop
dart pub global activate --source git https://github.com/ente-io/flutter_distributor_fork --git-ref develop --git-path packages/flutter_distributor
# RPM
flutter_distributor package --platform=linux --targets=rpm --skip-clean
mv dist/**/*-*-linux.rpm artifacts/ente-${{ github.ref_name }}-x86_64.rpm
# APPIMAGE
flutter_distributor package --platform=linux --targets=appimage --skip-clean
mv dist/**/*-*-linux.AppImage artifacts/ente-${{ github.ref_name }}-x86_64.AppImage
# DEB
# dart pub global activate flutter_distributor
dart pub global activate --source git https://github.com/prateekmedia/flutter_distributor --git-ref develop --git-path packages/flutter_distributor
flutter_distributor package --platform=linux --targets=deb --skip-clean
mv dist/**/*-*-linux.deb artifacts/ente-${{ github.ref_name }}-x86_64.deb
env:
LIBSODIUM_USE_PKGCONFIG: 1
- name: Generate checksums
run: sha256sum artifacts/ente-* >> artifacts/sha256sum-rpm-appimage
- name: Generate checksums and push to artifacts
run: |
sha256sum artifacts/ente-* > artifacts/sha256sum-apk-deb
- name: Create a draft GitHub release
uses: ncipollo/release-action@v1
@@ -134,6 +125,67 @@ jobs:
releaseFiles: auth/build/app/outputs/bundle/playstoreRelease/app-playstore-release.aab
track: internal
build-fedora-etc:
runs-on: ubuntu-latest
defaults:
run:
working-directory: auth
steps:
- name: Checkout code and submodules
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Flutter ${{ env.FLUTTER_VERSION }}
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Create artifacts directory
run: mkdir artifacts
- name: Install dependencies for desktop build
run: |
sudo apt-get update -y
sudo apt-get install -y libsecret-1-dev libsodium-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config rpm patchelf libsqlite3-dev locate libayatana-appindicator3-dev libffi-dev libtiff6 xz-utils libarchive-tools libcurl4-openssl-dev
sudo updatedb --localpaths='/usr/lib/x86_64-linux-gnu'
- name: Install appimagetool
run: |
wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x appimagetool
mv appimagetool /usr/local/bin/
- name: Build desktop app
run: |
flutter config --enable-linux-desktop
# dart pub global activate flutter_distributor
dart pub global activate --source git https://github.com/prateekmedia/flutter_distributor --git-ref develop --git-path packages/flutter_distributor
# Run below command if it is a beta or nightly
if [[ ${{ github.ref }} =~ beta|nightly ]]; then
flutter_distributor package --platform=linux --targets=pacman --skip-clean
mv dist/**/*-*-linux.pacman artifacts/ente-${{ github.ref_name }}-x86_64.pacman
fi
flutter_distributor package --platform=linux --targets=rpm --skip-clean
mv dist/**/*-*-linux.rpm artifacts/ente-${{ github.ref_name }}-x86_64.rpm
flutter_distributor package --platform=linux --targets=appimage --skip-clean
mv dist/**/*-*-linux.AppImage artifacts/ente-${{ github.ref_name }}-x86_64.AppImage
- name: Generate checksums
run: sha256sum artifacts/ente-* >> artifacts/sha256sum-rpm-appimage
- name: Create a draft GitHub release
uses: ncipollo/release-action@v1
with:
artifacts: "auth/artifacts/*"
draft: true
allowUpdates: true
updateOnlyUnreleased: true
build-windows:
runs-on: windows-latest
@@ -161,7 +213,7 @@ jobs:
run: |
flutter config --enable-windows-desktop
# dart pub global activate flutter_distributor
dart pub global activate --source git https://github.com/ente-io/flutter_distributor_fork --git-ref develop --git-path packages/flutter_distributor
dart pub global activate --source git https://github.com/prateekmedia/flutter_distributor --git-ref develop --git-path packages/flutter_distributor
make innoinstall
flutter_distributor package --platform=windows --targets=exe --skip-clean
mv dist/**/*-windows-setup.exe artifacts/ente-${{ github.ref_name }}-installer.exe

View File

@@ -36,6 +36,6 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Update branch ghcr/server to point to source commit
- name: Update branch server/ghcr to point to source commit
run: |
git push -f origin HEAD:refs/heads/ghcr/server
git push -f origin HEAD:refs/heads/server/ghcr

View File

@@ -1,34 +0,0 @@
name: "Publish ghcr (web)"
on:
# Run automatically every Wednesday, at 07:00 UTC.
schedule:
- cron: '0 7 * * 3'
# Run manually if needed to publish out of schedule.
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build and push
uses: mr-smithers-excellent/docker-build-push@v6
with:
dockerfile: web/Dockerfile
directory: web
# Resultant package name will be ghcr.io/ente-io/web
image: web
registry: ghcr.io
enableBuildKit: true
multiPlatform: true
platform: linux/amd64,linux/arm64
tags: ${{ github.sha }}, latest
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Update branch ghcr/web to point to source commit
run: |
git push -f origin HEAD:refs/heads/ghcr/web

3
.gitmodules vendored
View File

@@ -9,6 +9,3 @@
[submodule "auth/assets/simple-icons"]
path = auth/assets/simple-icons
url = https://github.com/simple-icons/simple-icons.git
[submodule "mobile/thirdparty/flutter"]
path = mobile/thirdparty/flutter
url = https://github.com/flutter/flutter.git

View File

@@ -350,7 +350,6 @@ class UserService {
userPassword,
_config.getKeyAttributes()!,
);
_config.resetVolatilePassword();
page = const HomePage();
} else {
throw Exception("unexpected response during passkey verification");

View File

@@ -41,14 +41,14 @@
"onnxruntime-node": "^1.20.1"
},
"devDependencies": {
"@eslint/js": "^9.22.0",
"@eslint/js": "^9.21.0",
"@tsconfig/node20": "^20.1.4",
"@types/auto-launch": "^5.0.5",
"@types/ffmpeg-static": "^3.0.3",
"ajv": "^8.17.1",
"concurrently": "^9.1.2",
"cross-env": "^7.0.3",
"electron": "^34.3.3",
"electron": "^34.3.1",
"electron-builder": "^26.0.0",
"eslint": "^9",
"prettier": "3.5.3",
@@ -56,7 +56,7 @@
"prettier-plugin-packagejson": "^2.5.10",
"shx": "^0.3.4",
"typescript": "^5.8.2",
"typescript-eslint": "^8.26.1"
"typescript-eslint": "^8.26.0"
},
"packageManager": "yarn@1.22.22",
"productName": "ente"

View File

@@ -404,11 +404,10 @@ const createMainWindow = () => {
// "The unresponsive event is fired when Chromium detects that your
// webContents is not responding to input messages for > 30 seconds."
window.webContents.on("unresponsive", () => {
// There is a known case when this can happen: When the user to select a
// folder to upload (Upload > Folder), the browser callback to us takes
// some time. When trying to upload very large folders on slower Windows
// machines, this can take up to 30 seconds.
log.warn("MainWindow's webContents are unresponsive");
log.error(
"MainWindow's webContents are unresponsive, will restart the renderer process",
);
window.webContents.forcefullyCrashRenderer();
});
window.on("close", (event) => {

View File

@@ -177,10 +177,10 @@
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.9.1.tgz#4a97e85e982099d6c7ee8410aacb55adaa576f06"
integrity sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==
"@eslint/js@^9.22.0":
version "9.22.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.22.0.tgz#4ff53649ded7cbce90b444b494c234137fa1aa3d"
integrity sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==
"@eslint/js@^9.21.0":
version "9.21.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.21.0.tgz#4303ef4e07226d87c395b8fad5278763e9c15c08"
integrity sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==
"@eslint/object-schema@^2.1.4":
version "2.1.4"
@@ -392,62 +392,62 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@8.26.1":
version "8.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz#3e48eb847924161843b092c87a9b65176b53782f"
integrity sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==
"@typescript-eslint/eslint-plugin@8.26.0":
version "8.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.0.tgz#7e880faf91f89471c30c141951e15f0eb3a0599e"
integrity sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==
dependencies:
"@eslint-community/regexpp" "^4.10.0"
"@typescript-eslint/scope-manager" "8.26.1"
"@typescript-eslint/type-utils" "8.26.1"
"@typescript-eslint/utils" "8.26.1"
"@typescript-eslint/visitor-keys" "8.26.1"
"@typescript-eslint/scope-manager" "8.26.0"
"@typescript-eslint/type-utils" "8.26.0"
"@typescript-eslint/utils" "8.26.0"
"@typescript-eslint/visitor-keys" "8.26.0"
graphemer "^1.4.0"
ignore "^5.3.1"
natural-compare "^1.4.0"
ts-api-utils "^2.0.1"
"@typescript-eslint/parser@8.26.1":
version "8.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.26.1.tgz#0e2f915a497519fc43f52cf2ecbfa607ff56f72e"
integrity sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==
"@typescript-eslint/parser@8.26.0":
version "8.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.26.0.tgz#9b4d2198e89f64fb81e83167eedd89a827d843a9"
integrity sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==
dependencies:
"@typescript-eslint/scope-manager" "8.26.1"
"@typescript-eslint/types" "8.26.1"
"@typescript-eslint/typescript-estree" "8.26.1"
"@typescript-eslint/visitor-keys" "8.26.1"
"@typescript-eslint/scope-manager" "8.26.0"
"@typescript-eslint/types" "8.26.0"
"@typescript-eslint/typescript-estree" "8.26.0"
"@typescript-eslint/visitor-keys" "8.26.0"
debug "^4.3.4"
"@typescript-eslint/scope-manager@8.26.1":
version "8.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz#5e6ad0ac258ccf79462e91c3f43a3f1f7f31a6cc"
integrity sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==
"@typescript-eslint/scope-manager@8.26.0":
version "8.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz#b06623fad54a3a77fadab5f652ef75ed3780b545"
integrity sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==
dependencies:
"@typescript-eslint/types" "8.26.1"
"@typescript-eslint/visitor-keys" "8.26.1"
"@typescript-eslint/types" "8.26.0"
"@typescript-eslint/visitor-keys" "8.26.0"
"@typescript-eslint/type-utils@8.26.1":
version "8.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz#462f0bae09de72ac6e8e1af2ebe588c23224d7f8"
integrity sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==
"@typescript-eslint/type-utils@8.26.0":
version "8.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.26.0.tgz#9ee8cc98184b5f66326578de9c097edc89da6f68"
integrity sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==
dependencies:
"@typescript-eslint/typescript-estree" "8.26.1"
"@typescript-eslint/utils" "8.26.1"
"@typescript-eslint/typescript-estree" "8.26.0"
"@typescript-eslint/utils" "8.26.0"
debug "^4.3.4"
ts-api-utils "^2.0.1"
"@typescript-eslint/types@8.26.1":
version "8.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.26.1.tgz#d5978721670cff263348d5062773389231a64132"
integrity sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==
"@typescript-eslint/types@8.26.0":
version "8.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.26.0.tgz#c4e93a8faf3a38a8d8adb007dc7834f1c89ee7bf"
integrity sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==
"@typescript-eslint/typescript-estree@8.26.1":
version "8.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz#eb0e4ce31753683d83be53441a409fd5f0b34afd"
integrity sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==
"@typescript-eslint/typescript-estree@8.26.0":
version "8.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz#128972172005a7376e34ed2ecba4e29363b0cad1"
integrity sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==
dependencies:
"@typescript-eslint/types" "8.26.1"
"@typescript-eslint/visitor-keys" "8.26.1"
"@typescript-eslint/types" "8.26.0"
"@typescript-eslint/visitor-keys" "8.26.0"
debug "^4.3.4"
fast-glob "^3.3.2"
is-glob "^4.0.3"
@@ -455,22 +455,22 @@
semver "^7.6.0"
ts-api-utils "^2.0.1"
"@typescript-eslint/utils@8.26.1":
version "8.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.26.1.tgz#54cc58469955f25577f659753b71a0e117a0539f"
integrity sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==
"@typescript-eslint/utils@8.26.0":
version "8.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.26.0.tgz#845d20ed8378a5594e6445f54e53b972aee7b3e6"
integrity sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
"@typescript-eslint/scope-manager" "8.26.1"
"@typescript-eslint/types" "8.26.1"
"@typescript-eslint/typescript-estree" "8.26.1"
"@typescript-eslint/scope-manager" "8.26.0"
"@typescript-eslint/types" "8.26.0"
"@typescript-eslint/typescript-estree" "8.26.0"
"@typescript-eslint/visitor-keys@8.26.1":
version "8.26.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz#c5267fcc82795cf10280363023837deacad2647c"
integrity sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==
"@typescript-eslint/visitor-keys@8.26.0":
version "8.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz#a4876216756c69130ea958df3b77222c2ad95290"
integrity sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==
dependencies:
"@typescript-eslint/types" "8.26.1"
"@typescript-eslint/types" "8.26.0"
eslint-visitor-keys "^4.2.0"
"@xmldom/xmldom@^0.8.8":
@@ -1264,10 +1264,10 @@ electron-updater@^6.4.0:
semver "^7.6.3"
tiny-typed-emitter "^2.1.0"
electron@^34.3.3:
version "34.3.3"
resolved "https://registry.yarnpkg.com/electron/-/electron-34.3.3.tgz#2979329d182a195756bfbf6e5687a835cd65a2ec"
integrity sha512-7m1FiO1mwc1K/UqqnnkG7Ik/kAngDzmLfHwcl+xaWgCQ+Sts9rlEqzOh6g1GHhDqebrbs4bO/aU+NDi32fCciQ==
electron@^34.3.1:
version "34.3.1"
resolved "https://registry.yarnpkg.com/electron/-/electron-34.3.1.tgz#2c337a496d923463a2c7be7eaab191ad8220459b"
integrity sha512-Vsgxc4FDGg7hjduKyvTP5qfNDxZHTliZIiWD1HlR5hHXx3BFjyVv3db/uEH1GaCU0KKyeNsBXRwS4WAOMaSH5g==
dependencies:
"@electron/get" "^2.0.0"
"@types/node" "^20.9.0"
@@ -3209,14 +3209,14 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
typescript-eslint@^8.26.1:
version "8.26.1"
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.26.1.tgz#d17a638a7543bc535157b83cdf5876513c71493b"
integrity sha512-t/oIs9mYyrwZGRpDv3g+3K6nZ5uhKEMt2oNmAPwaY4/ye0+EH4nXIPYNtkYFS6QHm+1DFg34DbglYBz5P9Xysg==
typescript-eslint@^8.26.0:
version "8.26.0"
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.26.0.tgz#f44cafdaa6edc99e3612b33b791eb77a56286320"
integrity sha512-PtVz9nAnuNJuAVeUFvwztjuUgSnJInODAUx47VDwWPXzd5vismPOtPtt83tzNXyOjVQbPRp786D6WFW/M2koIA==
dependencies:
"@typescript-eslint/eslint-plugin" "8.26.1"
"@typescript-eslint/parser" "8.26.1"
"@typescript-eslint/utils" "8.26.1"
"@typescript-eslint/eslint-plugin" "8.26.0"
"@typescript-eslint/parser" "8.26.0"
"@typescript-eslint/utils" "8.26.0"
typescript@^5.4.3:
version "5.5.4"

View File

@@ -142,7 +142,6 @@ export const sidebar = [
text: "Video streaming",
link: "/photos/faq/video-streaming",
},
{ text: "Misc", link: "/photos/faq/misc" },
],
},
{
@@ -312,10 +311,6 @@ export const sidebar = [
text: "Uploads",
link: "/self-hosting/troubleshooting/uploads",
},
{
text: "Docker",
link: "/self-hosting/troubleshooting/docker",
},
{
text: "Yarn",
link: "/self-hosting/troubleshooting/yarn",

View File

@@ -117,26 +117,13 @@ clicking on "Your map" under "Locations" on the search screen.
On the login page, enter your email and click on Forgot Password. Then, enter your recovery key and create a new password.
# iOS Album Backup and Organization in Ente
# iOS Album Backup and Organization in Ente
### How does Ente handle photos that are part of multiple iOS albums?
### How does Ente handle photos that are part of multiple iOS albums?
When you select multiple albums for backup, Ente prioritizes uploading each photo to the album with the fewest photos. This means a photo will only be uploaded once, even if it exists in multiple albums on your device. If you create new albums on your device after the initial backup, those photos may not appear in the corresponding Ente album if they were already uploaded to a different album.
### Why dont all photos from a new iOS album appear in the corresponding Ente album?
If you create a new album on your device after the initial backup, the photos in that album may have already been uploaded to another album in Ente. To fix this, go to the "On Device" album in Ente, select all photos, and manually add them to the corresponding album in Ente.
### What happens if I reorganize my photos in the iOS Photos app after backing up?
Reorganizing photos in the iOS Photos app (e.g., moving photos to new albums) wont automatically reflect in Ente. Youll need to manually add those photos to the corresponding albums in Ente to maintain consistency.
### Can I search for photos using the descriptions Ive added?
Yes, descriptions are searchable, making it easier to find specific photos later.
To do this, open the photo, tap the (i) button, and enter your description.
### How does the deduplication feature work on the desktop app?
If the app finds exact duplicates, it will show them in the deduplication. When you delete a duplicate, the app keeps one copy and creates a symlink for the other duplicate. This helps save storage space.
### What happens if I lose access to my email address? Can I use my recovery key to bypass email verification?
No, the recovery key does not bypass email verification. For security reasons, we do not disable or bypass email verification unless the account owner reaches out to us and successfully verifies their identity by providing details about their account.
If you lose access to your email, please contact our support team at support@ente.io
Reorganizing photos in the iOS Photos app (e.g., moving photos to new albums) wont automatically reflect in Ente. Youll need to manually add those photos to the corresponding albums in Ente to maintain consistency

View File

@@ -1,20 +0,0 @@
---
title: Miscellaneous general FAQ
description: Unsorted frequently asked questions about Ente Photos
---
# Miscellaneous FAQ
## Exif Description
Ente will try to read as much information from Exif when the image is uploaded,
but after that, only the fields which have been parsed into Ente can be
searched.
The app still show all the fields in the raw Exif data in the file info panel
when someone taps on the "View all Exif" option, but otherwise the app is
unaware of these fields.
In particular, for the description associated with a photo, the exact logic to
determine the description from the Exif when uploading the image can be seen
[in this part of the code](https://github.com/ente-io/ente/blob/0dcb185744da469848b41b668fe4b647226b6fe2/web/packages/gallery/services/exif.ts#L609-L620).

View File

@@ -12,11 +12,6 @@ verification code by:
- Reading it from the DB (otts table)
> [!TIP]
>
> You can also configure your instance to send out emails so that you can get
> your verification code via emails by using the `smtp` section in the config.
You can also set pre-defined hardcoded OTTs for certain users when running
locally by creating a `museum.yaml` and adding the `internal.hardcoded-ott`
configuration setting to it. See

View File

@@ -9,11 +9,11 @@ description:
> [!NOTE]
>
> This is a community contributed guide, and some of these steps ~~might be~~
> ARE out of sync with the upstream changes. This document is retained for
> reference purposes, but if something is not working correctly, please see the
> latest [READMEs](https://github.com/ente-io/ente/blob/main/server/README.md)
> in the repository and/or other guides in [self-hosting](/self-hosting/).
> This is a community contributed guide, and some of these steps might be out of
> sync with the upstream documentation. If something is not working correctly,
> please also see the latest
> [READMEs](https://github.com/ente-io/ente/blob/main/server/README.md) in the
> repository and/or other guides in [self-hosting](/self-hosting/).
This guide is for self hosting the server and the web application of Ente Photos
using docker compose and an external S3 bucket. So we assume that you already

View File

@@ -30,6 +30,10 @@ longer term, then it is recommended to follow the Docker approach.
> [!IMPORTANT]
>
> This docker image is still in testing stage and it might show up with some
> unknown variables in different scenarios. But this image has been tested on a
> production Ente site.
>
> Recurring changes might be made by the team or from community if more
> improvements can be made so that we are able to build a full-fledged docker
> image.
@@ -46,8 +50,8 @@ COPY apps/ .
RUN corepack enable
# Endpoint for Ente Server
ENV NEXT_PUBLIC_ENTE_ENDPOINT=https://changeme.com
ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=https://changeme.com
ENV NEXT_PUBLIC_ENTE_ENDPOINT=https://your-ente-endpoint.com
ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=https://your-albums-endpoint.com
RUN yarn cache clean
RUN yarn install --network-timeout 1000000000
@@ -138,6 +142,75 @@ docker compose up -d # --build
docker compose logs <container-name>
```
## Without Docker / Docker compose
One way to run all the apps together without Docker is by using
[PM2](https://pm2.keymetrics.io/) in this setup. The configuration and usage is
very simple and just needs one configuration file for it. You can run the apps
both in dev server mode as well as static files.
The below configuration will run the apps in dev server mode.
### Install PM2
```sh
npm install pm2@latest
```
Copy the below contents to a file called `ecosystem.config.js` inside the
`ente/web` directory.
```js
module.exports = {
apps: [
{
name: "photos",
script: "yarn workspace photos next dev",
env: {
NODE_ENV: "development",
PORT: "3000"
}
},
{
name: "accounts",
script: "yarn workspace accounts next dev",
env: {
NODE_ENV: "development",
PORT: "3001"
}
},
{
name: "auth",
script: "yarn workspace auth next dev",
env: {
NODE_ENV: "development",
PORT: "3002"
}
},
{
name: "cast",
script: "yarn workspace cast next dev",
env: {
NODE_ENV: "development",
PORT: "3003"
}
}
]
};
```
Finally, start pm2.
```sh
pm2 start
# for logs
pm2 logs all
```
## Configure App Endpoints
> [!NOTE]

View File

@@ -14,34 +14,7 @@ the same code we use for our own cloud service.
> [blog post](https://ente.io/blog/open-sourcing-our-server/) announcing the
> open sourcing of our server useful.
## Getting started - Quickstart
Install [Docker](https://www.docker.com). Then, paste the following command in a
your terminal:
```sh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ente-io/ente/main/server/quickstart.sh)"
```
> [!TIP]
>
> For more details about what this does, see [the quickstart
> README](https://github.com/ente-io/ente/blob/main/server/docs/quickstart.md).
That's about it. If you open http://localhost:3000, you will be able to create
an account on a Ente Photos web app running on your machine, and this web app
will be connecting to the server running on your local machine at
`localhost:8080`. The verification code will be shown in the server logs.
For the mobile or desktop apps, you don't even need to build, and can install
normal Ente apps and configure them to use your
[custom self-hosted server](guides/custom-server/).
## Getting started - From source
The quickstart method above uses pre-built images. Alternatively, if you want to
build the self hosted server images from source, you can use the steps in this
section.
## Getting started
#### Installing Docker
@@ -57,6 +30,11 @@ cd ente/server
docker compose up --build
```
> [!TIP]
>
> You can also use a pre-built Docker image from `ghcr.io/ente-io/server`
> ([More info](https://github.com/ente-io/ente/blob/main/server/docs/docker.md))
Install the necessary dependencies for running the web client
```sh
@@ -75,6 +53,15 @@ yarn install
NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:8080 yarn dev
```
That's about it. If you open http://localhost:3000, you will be able to create
an account on a Ente Photos web app running on your machine, and this web app
will be connecting to the server running on your local machine at
`localhost:8080`.
For the mobile apps, you don't even need to build, and can install normal Ente
apps and configure them to use your
[custom self-hosted server](guides/custom-server/).
> If you want to build the mobile apps from source, see the instructions
> [here](guides/mobile-build).

View File

@@ -1,72 +0,0 @@
---
title: Docker errors
description: Fixing docker related errors when trying to self host Ente
---
# Docker
## configs
Remember to restart your cluster to ensure changes that you make in the
`configs` section in `compose.yaml` get picked up.
```sh
docker compose down
docker compose up
```
## post_start
The `server/compose.yaml` Docker compose file uses the "post_start" lifecycle
hook to provision the MinIO instance.
The lifecycle hook **requires Docker Compose version 2.30.0+**, and if you're
using an older version of docker compose you will see an error like this:
```
validating compose.yaml: services.minio Additional property post_start is not allowed
```
The easiest way to resolve this is to upgrade your Docker compose.
If you cannot update your Docker compose version, then alternatively you can
perform the same configuration by removing the "post_start" hook, and adding a
new service definition:
```yaml
minio-provision:
image: minio/mc
depends_on:
- minio
volumes:
- minio-data:/data
networks:
- internal
entrypoint: |
sh -c '
#!/bin/sh
while ! mc config host add h0 http://minio:3200 changeme changeme1234
do
echo "waiting for minio..."
sleep 0.5
done
cd /data
mc mb -p b2-eu-cen
mc mb -p wasabi-eu-central-2-v3
mc mb -p scw-eu-fr-v3
'
```
## start_interval
Similar to the `post_start` case above, if you are seeing an error like
```
services.postgres.healthcheck Additional property start_interval is not allowed
```
You will need to upgrade your Docker compose version to a newer version that
supports the `start_interval` property on the health check.

View File

@@ -5,8 +5,7 @@ description: Fixing yarn install errors when trying to self host Ente
# Yarn
If your `yarn install` is failing, make sure you are using Yarn v1 (also known
as "Yarn Classic"):
If your `yarn install` is failing, make sure you are using Yarn Classic
- https://classic.yarnpkg.com/lang/en/docs/install

View File

@@ -2,7 +2,6 @@ plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
id 'org.jetbrains.kotlin.plugin.serialization' version '2.1.10'
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
@@ -82,6 +81,10 @@ android {
dimension "default"
applicationIdSuffix ".dev"
}
face {
dimension "default"
applicationIdSuffix ".face"
}
playstore {
dimension "default"
}
@@ -134,8 +137,7 @@ flutter {
dependencies {
implementation 'io.sentry:sentry-android:2.0.0'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21"
implementation 'com.android.support:multidex:1.0.3'
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.8.1'

View File

@@ -1,27 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="io.ente.photos">
<!-- Adding the following block to prevent the app from having multiple
launcher entries. We can remove this along with the `LAUNCHER` category from
main/AndroidManifest.xml once
https://github.com/flutter/flutter/issues/38965 is fixed. -->
<application>
<activity android:name=".MainActivity"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:exported="true"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" tools:node="remove"/>
</intent-filter>
</activity>
</application>
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->

View File

@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.ente.photos">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

View File

@@ -0,0 +1,4 @@
<resources>
<string name="app_name">Ente Face</string>
<string name="backup">backup face</string>
</resources>

View File

@@ -1,25 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
package="io.ente.photos">
<!-- Adding the following block to prevent the app from having multiple
launcher entries. We can remove this along with the `LAUNCHER` category from
main/AndroidManifest.xml once
https://github.com/flutter/flutter/issues/38965 is fixed. -->
<application>
<activity android:name=".MainActivity"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:exported="true"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" tools:node="remove"/>
</intent-filter>
</activity>
</application>
<uses-permission android:name="com.android.vending.BILLING" tools:node="remove"/>
</manifest>

View File

@@ -1,24 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="io.ente.photos">
<!-- Adding the following block to prevent the app from having multiple
launcher entries. We can remove this along with the `LAUNCHER` category from
main/AndroidManifest.xml once
https://github.com/flutter/flutter/issues/38965 is fixed. -->
<application>
<activity android:name=".MainActivity"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:exported="true"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" tools:node="remove"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,11 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="io.ente.photos">
<application
tools:replace="android:label"
android:name="${applicationName}"
<application android:name="${applicationName}"
android:label="@string/app_name"
android:icon="@mipmap/icon_green"
android:icon="@mipmap/launcher_icon"
android:usesCleartextTraffic="true"
android:requestLegacyExternalStorage="true"
android:allowBackup="false"
@@ -19,11 +17,8 @@
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="es.antonborri.home_widget.action.LAUNCH" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -90,50 +85,6 @@
</intent-filter>
</activity>
<activity-alias
android:name="${applicationId}.IconGreen"
android:icon="@mipmap/icon_green"
android:enabled="true"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
<activity-alias
android:name="${applicationId}.IconLight"
android:icon="@mipmap/icon_light"
android:enabled="false"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
<activity-alias
android:name="${applicationId}.IconDark"
android:icon="@mipmap/icon_dark"
android:enabled="false"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
<activity-alias
android:name="${applicationId}.IconOG"
android:icon="@mipmap/icon_og"
android:enabled="false"
android:exported="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
@@ -145,12 +96,12 @@
android:value="https://2235e5c99219488ea93da34b9ac1cb68@sentry.ente.io/4" />
<meta-data android:name="firebase_analytics_collection_deactivated"
android:value="true" />
<receiver android:name="EnteMemoryWidgetProvider" android:label="Memories" android:exported="true">
<receiver android:name="SlideshowWidgetProvider" android:label="Favorites" android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/memory_widget" />
android:resource="@xml/slideshow_widget" />
</receiver>
</application>

View File

@@ -1,198 +0,0 @@
package io.ente.photos
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import androidx.core.content.ContextCompat
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
import java.io.File
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
@Serializable
data class MemoryFileData(val title: String?, val subText: String?, val generatedId: Int?)
class EnteMemoryWidgetProvider : HomeWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray,
widgetData: SharedPreferences
) {
appWidgetIds.forEach { widgetId ->
val views =
RemoteViews(context.packageName, R.layout.memory_widget_layout)
.apply {
val totalMemories =
widgetData.getInt("totalMemories", 0)
var randomNumber = -1
var imagePath: String? = null
if (totalMemories > 0) {
randomNumber =
(0 until totalMemories!!).random()
imagePath =
widgetData.getString(
"memory_widget_" +
randomNumber,
null
)
}
var imageExists: Boolean = false
if (imagePath != null) {
val imageFile = File(imagePath)
imageExists = imageFile.exists()
}
if (imageExists) {
val data =
widgetData.getString(
"memory_widget_${randomNumber}_data",
null
)
val decoded: MemoryFileData? =
data?.let {
Json.decodeFromString<
MemoryFileData>(it)
}
val title = decoded?.title
val subText = decoded?.subText
val generatedId = decoded?.generatedId
val deepLinkUri =
Uri.parse(
"memorywidget://message?generatedId=${generatedId}&homeWidget"
)
val pendingIntent =
HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
deepLinkUri
)
setOnClickPendingIntent(
R.id.widget_container,
pendingIntent
)
Log.d(
"EnteMemoryWidgetProvider",
"Image exists: $imagePath"
)
setViewVisibility(
R.id.widget_img,
View.VISIBLE
)
setViewVisibility(
R.id.widget_placeholder_container,
View.VISIBLE
)
setViewVisibility(
R.id.widget_subtitle,
View.VISIBLE
)
setViewVisibility(
R.id.widget_title,
View.VISIBLE
)
setViewVisibility(
R.id.widget_overlay,
View.VISIBLE
)
setViewVisibility(
R.id.widget_placeholder,
View.GONE
)
setViewVisibility(
R.id.widget_placeholder_text,
View.GONE
)
setViewVisibility(
R.id.widget_placeholder_container,
View.GONE
)
val bitmap: Bitmap =
BitmapFactory.decodeFile(imagePath)
setImageViewBitmap(R.id.widget_img, bitmap)
setTextViewText(R.id.widget_title, title)
setTextViewText(
R.id.widget_subtitle,
subText
)
} else {
// Open App on Widget Click
val pendingIntent =
HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java
)
setOnClickPendingIntent(
R.id.widget_container,
pendingIntent
)
Log.d(
"EnteMemoryWidgetProvider",
"Image doesn't exists"
)
setViewVisibility(
R.id.widget_img,
View.GONE
)
setViewVisibility(
R.id.widget_placeholder_container,
View.GONE
)
setViewVisibility(
R.id.widget_subtitle,
View.GONE
)
setViewVisibility(
R.id.widget_title,
View.GONE
)
setViewVisibility(
R.id.widget_overlay,
View.GONE
)
setViewVisibility(
R.id.widget_placeholder,
View.VISIBLE
)
setViewVisibility(
R.id.widget_placeholder_text,
View.VISIBLE
)
setViewVisibility(
R.id.widget_placeholder_container,
View.VISIBLE
)
val drawable =
ContextCompat.getDrawable(
context,
R.drawable
.ic_home_widget_default
)
val bitmap =
(drawable as BitmapDrawable).bitmap
setImageViewBitmap(
R.id.widget_placeholder,
bitmap
)
}
}
appWidgetManager.updateAppWidget(widgetId, views)
}
}
}

View File

@@ -0,0 +1,67 @@
package io.ente.photos
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import androidx.core.content.ContextCompat
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
import java.io.File
class SlideshowWidgetProvider : HomeWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray,
widgetData: SharedPreferences
) {
appWidgetIds.forEach { widgetId ->
val views =
RemoteViews(context.packageName, R.layout.slideshow_layout).apply {
// Open App on Widget Click
val pendingIntent =
HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java
)
setOnClickPendingIntent(R.id.widget_container, pendingIntent)
// Show Images saved with `renderFlutterWidget`
val imagePath = widgetData.getString("slideshow", null)
var imageExists: Boolean = false
if (imagePath != null) {
val imageFile = File(imagePath)
imageExists = imageFile.exists()
}
if (imageExists) {
Log.d("SlideshowWidgetProvider", "Image exists: $imagePath")
setViewVisibility(R.id.widget_img, View.VISIBLE)
setViewVisibility(R.id.widget_placeholder, View.GONE)
val bitmap: Bitmap = BitmapFactory.decodeFile(imagePath)
setImageViewBitmap(R.id.widget_img, bitmap)
} else {
Log.d("SlideshowWidgetProvider", "Image doesn't exists")
setViewVisibility(R.id.widget_img, View.GONE)
setViewVisibility(R.id.widget_placeholder, View.VISIBLE)
val drawable =
ContextCompat.getDrawable(
context,
R.drawable.ic_home_widget_default
)
val bitmap = (drawable as BitmapDrawable).bitmap
setImageViewBitmap(R.id.widget_placeholder, bitmap)
}
}
appWidgetManager.updateAppWidget(widgetId, views)
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B

After

Width:  |  Height:  |  Size: 70 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B

After

Width:  |  Height:  |  Size: 70 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -1,8 +0,0 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:startColor="#80000000"
android:endColor="#00000000"
android:centerY="1.0"
android:centerColor="#20000000"/>
</shape>

View File

@@ -1,84 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/widget_container">
<!-- Main Image (if available) -->
<ImageView
android:id="@+id/widget_img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:visibility="gone" /> <!-- Initially hidden -->
<!-- Gradient Overlay for Text Readability -->
<LinearLayout
android:id="@+id/widget_overlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingBottom="16dp"
android:paddingTop="4dp"
android:background="@layout/gradient_overlay"
android:visibility="gone"> <!-- Initially hidden, shown when image is available -->
<!-- Title -->
<TextView
android:id="@+id/widget_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold"
android:maxLines="1"
android:ellipsize="end"
android:visibility="gone"/>
<!-- Subtitle -->
<TextView
android:id="@+id/widget_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="@android:color/white"
android:textSize="12sp"
android:maxLines="1"
android:ellipsize="end"
android:visibility="gone"/>
</LinearLayout>
<!-- Placeholder View (when no image available) -->
<LinearLayout
android:id="@+id/widget_placeholder_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:background="@color/widget_placeholder_bg">
<ImageView
android:id="@+id/widget_placeholder"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@drawable/ic_home_widget_default"
android:scaleType="fitCenter" />
<TextView
android:id="@+id/widget_placeholder_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Your memories will appear here"
android:textSize="14sp"
android:gravity="center_horizontal"
android:textColor="@color/widget_text_color"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:layout_marginTop="12dp"/>
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/widget_container">
<ImageView
android:id="@+id/widget_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:visibility="visible"
tools:visibility="visible"
/>
<ImageView
android:id="@+id/widget_img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:visibility="visible"
tools:visibility="visible"
/>
</LinearLayout>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background_dark"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_monochrome_launcher_foreground"/>
</adaptive-icon>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_monochrome_launcher_foreground"/>
</adaptive-icon>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background_light"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_monochrome_launcher_foreground"/>
</adaptive-icon>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background_light"/>
<foreground android:drawable="@drawable/ic_og_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_og_launcher_foreground"/>
</adaptive-icon>

View File

@@ -2,5 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_monochrome_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Some files were not shown because too many files have changed in this diff Show More