275 changed files with 178 additions and 1450 deletions
-11
View File
@@ -1,11 +0,0 @@
.git
.github
node_modules
dist
.astro
.vscode
.idea
*.log
.DS_Store
README.md
LICENSE
+97
View File
@@ -0,0 +1,97 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '23 16 * * 1'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- name: Run manual build steps
if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
-77
View File
@@ -1,77 +0,0 @@
name: Portfolio-synk (Immich → portfolio)
on:
schedule:
- cron: '0 3 * * *' # dygnsvis 03:00 UTC
workflow_dispatch: # "på begäran" — manuell knapp / API-trigger
permissions:
contents: write # för att committa nya bilder
concurrency:
group: portfolio-sync # ingen parallell körning (race-skydd)
cancel-in-progress: false
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install sharp
run: npm install sharp@^0.33.5
- name: Run portfolio sync
id: sync
env:
IMMICH_API_KEY: ${{ secrets.IMMICH_API_KEY }}
run: node scripts/portfolio-sync.mjs
- name: Commit, PR & auto-merge if changed
if: steps.sync.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.SYNC_PAT }}
SYNC_PAT: ${{ secrets.SYNC_PAT }}
REPO: ${{ github.repository }}
ADDED: ${{ steps.sync.outputs.added }}
REMOVED: ${{ steps.sync.outputs.removed }}
run: |
set -e
BRANCH="sync/portfolio-$(date +%Y%m%d-%H%M%S)"
git config user.name "portfolio-sync[bot]"
git config user.email "actions@github.com"
git checkout -b "$BRANCH"
git add src/assets/images/portfolio/
git commit -m "chore(portfolio): sync ${ADDED} added, ${REMOVED} removed from Immich"
git push "https://x-access-token:${SYNC_PAT}@github.com/${REPO}.git" "$BRANCH"
gh pr create --head "$BRANCH" --base main \
--title "chore(portfolio): Immich sync (${ADDED} added, ${REMOVED} removed)" \
--body "Automated portfolio sync from Immich portfolio tag."
gh pr merge "$BRANCH" --squash --admin --delete-branch
# Coolify auto-deployar på push till main (webhook) — GitHub-runnern når
# inte Coolify (Tailscale-IP 100.x), så vi triggar inte härifrån.
- name: Wait for Coolify auto-deploy
if: steps.sync.outputs.changed == 'true'
run: sleep 120
- name: Purge Cloudflare cache
if: steps.sync.outputs.changed == 'true'
run: |
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/22c7ed24735e7417d814ef66d90e4397/purge_cache" \
-H "Authorization: Bearer ${{ secrets.CF_PURGE_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{"files":["https://imagesbyolofsson.se/portfolio"]}' || echo "CF-purge misslyckades (icke-kritiskt)"
- name: Summary
run: |
echo "### Portfolio-synk klar" >> $GITHUB_STEP_SUMMARY
echo "- Tillagda: ${{ steps.sync.outputs.added }}" >> $GITHUB_STEP_SUMMARY
echo "- Borttagna: ${{ steps.sync.outputs.removed }}" >> $GITHUB_STEP_SUMMARY
echo "- Ändring: ${{ steps.sync.outputs.changed }}" >> $GITHUB_STEP_SUMMARY
-21
View File
@@ -1,21 +0,0 @@
# syntax=docker/dockerfile:1.7
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN --mount=type=cache,target=/root/.npm \
if [ -f package-lock.json ]; then npm ci; else npm install --no-audit --no-fund; fi
COPY . .
RUN npm run build
FROM nginx:1.27-alpine AS runtime
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
RUN adduser -D -H -u 101 -s /sbin/nologin nginxuser 2>/dev/null || true
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget -q --spider http://127.0.0.1/ || exit 1
+15 -95
View File
@@ -1,102 +1,22 @@
# Images by Olofsson # Homepage
A modern, responsive photography portfolio website built with Astro, Tailwind CSS, and advanced animations. Welcome to the Homepage!\
![Image 3](img3.jpg)\
![Image 4](img4.jpg)\
<br> ## Navigation
<div align="center"> - Home\
<table> - About\
<tr> - Contact\
<td align="center">
<img src="https://raw.githubusercontent.com/Images-by-Olofsson/homepage/main/public/3d-scroll/img1.jpg" width="250" alt="Portfolio Grid">
<br><em> More </em>
</td>
<td align="center">
<img src="https://raw.githubusercontent.com/Images-by-Olofsson/homepage/main/public/3d-scroll/img2.jpg" width="250" alt="3D Scroll Effect">
<br><em> At </em>
</td>
<td align="center">
<img src="https://raw.githubusercontent.com/Images-by-Olofsson/homepage/main/public/3d-scroll/img3.jpg" width="250" alt="Hero Section">
<br><em>Imagesbyolofsson.se</em>
</td>
</tr>
</table>
</div>
<br> This is a modern design layout that showcases our projects. The use of images and text is intended to maintain an aesthetic appeal.<br>
<br>
## Features ## Gallery
Modern design with minimalist aesthetics and focus on imagery. Advanced animations including wave effects, 3D scroll transforms, and smoke particles. Fully responsive across all devices with optimized performance. Here are some images that represent our work:<br>
- ![Image 1](img1.jpg)<br>
- ![Image 2](img2.jpg)<br>
- ![Image 3](img3.jpg)<br>
<br> Thank you for visiting!
## Quick Start
**Prerequisites**
Node.js 18.0 or higher
**Installation**
```bash
git clone https://github.com/Images-by-Olofsson/homepage.git
cd homepage
npm install
```
**Development**
```bash
npm run dev
```
**Build**
```bash
npm run build
npm run preview
```
<br>
## Project Structure
```
src/
├── assets/
├── components/
│ ├── WaveBackground.astro
│ ├── ThreeDScroll.astro
│ ├── FloatingOrbs.astro
│ └── Welcome.astro
├── layouts/
│ ├── MainLayout.astro
│ └── Layout.astro
├── pages/
│ ├── index.astro
│ ├── portfolio.astro
│ ├── about.astro
│ └── contact.astro
└── styles/
└── global.css
```
<br>
## Technologies
Astro, Tailwind CSS, TypeScript, Exifr
<br>
## License
MIT License - see LICENSE file for details
<br>
<div align="center">
<p>Built by Linus Olofsson</p>
</div>
-8
View File
@@ -1,8 +0,0 @@
import { defineConfig } from 'astro/config';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
vite: {
plugins: [tailwindcss()],
},
});
-46
View File
@@ -1,46 +0,0 @@
map $sent_http_content_type $cache_control_strategy {
default "public, max-age=2592000";
~^text/html "no-store, must-revalidate";
~^text/css "public, max-age=31536000, immutable";
~^application/javascript "public, max-age=31536000, immutable";
~^application/json "no-store, must-revalidate";
~^image/ "public, max-age=2592000";
~^font/ "public, max-age=31536000, immutable";
}
server {
listen 80 default_server;
server_name _;
root /usr/share/nginx/html;
index index.html;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Cache-Control $cache_control_strategy always;
location / {
try_files $uri $uri/ $uri.html $uri/index.html =404;
}
location /_astro/ {
access_log off;
expires 1y;
}
location ~* \.(webp|avif|jpg|jpeg|png|gif|svg|ico|woff2?|ttf|otf|eot)$ {
access_log off;
expires 30d;
}
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss image/svg+xml;
error_page 404 /404.html;
location = /404.html {
internal;
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

-32
View File
@@ -1,32 +0,0 @@
// Engangsjobb: skapa -s (800px) och -m (1600px) for redan synkade portfolio-bilder.
// Kallan ar den befintliga 3000px-filen i repot - ingen ny nedladdning fran Immich.
import fs from "node:fs";
import path from "node:path";
import sharp from "sharp";
const DIR = "src/assets/images/portfolio";
const SIZES = [{ suffix: "-s", dim: 800 }, { suffix: "-m", dim: 1600 }];
const QUALITY = 88;
const files = fs.readdirSync(DIR).filter(
(f) => /^immich-[0-9a-f-]{36}-/i.test(f) && /\.jpg$/i.test(f) && !/-[sm]\.jpg$/i.test(f)
);
console.log(`hittade ${files.length} large-bilder`);
let skapade = 0, hoppade = 0;
for (const f of files) {
const src = path.join(DIR, f);
const base = src.replace(/\.jpg$/i, "");
for (const { suffix, dim } of SIZES) {
const dest = `${base}${suffix}.jpg`;
if (fs.existsSync(dest)) { hoppade++; continue; }
await sharp(src)
.rotate()
.resize(dim, dim, { fit: "inside", withoutEnlargement: true })
.withMetadata()
.jpeg({ quality: QUALITY })
.toFile(dest);
skapade++;
}
}
console.log(`klart: ${skapade} skapade, ${hoppade} fanns redan`);
-131
View File
@@ -1,131 +0,0 @@
#!/usr/bin/env node
// Portfolio-synk: speglar Immich "portfolio"-taggade bilder till src/assets/images/portfolio/
// Självläkande: härleder synkat tillstånd från immich-<assetId>-*-filnamn i repot.
// Bevarar EXIF (portfolion läser DateTimeOriginal/Model/ISO för år/månad-filter + lightbox).
import fs from "node:fs";
import path from "node:path";
import sharp from "sharp";
const IMMICH = process.env.IMMICH_URL || "https://foto.imagesbyolofsson.se/api";
const KEY = process.env.IMMICH_API_KEY;
const TAGID = process.env.PORTFOLIO_TAG_ID || "67d16b6c-0dea-42ef-a289-2c9e57fa5c5a";
const PORTFOLIO_DIR = "src/assets/images/portfolio";
const MAX_DIM = 3000;
const JPEG_QUALITY = 88;
// RAW-format som sharp/libvips inte kan konvertera — hoppas över elegant.
// Tagga JPEG-versionen (redigera RAW → exportera JPEG → tagga den) istället.
const RAW_EXTENSIONS = [".cr2", ".cr3", ".arw", ".nef", ".dng", ".raf", ".orf", ".rw2", ".pef", ".srw"];
function isRaw(name) {
const lower = name.toLowerCase();
return RAW_EXTENSIONS.some((ext) => lower.endsWith(ext));
}
if (!KEY) { console.error("IMMICH_API_KEY saknas"); process.exit(1); }
async function api(method, pathname, body) {
const res = await fetch(IMMICH + pathname, {
method,
headers: { "x-api-key": KEY, "Content-Type": "application/json" },
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) throw new Error(`${method} ${pathname} → ${res.status}: ${(await res.text()).slice(0, 200)}`);
return res;
}
// Hämta alla portfolio-taggade assets (paginerat, unikt på id — search/metadata ger dubbletter över sidgräns)
async function fetchTagged() {
const map = new Map();
let page = 1;
while (true) {
const res = await api("POST", "/search/metadata", { tagIds: [TAGID], size: 250, page });
const d = await res.json();
const items = d.assets.items;
if (!items.length) break;
for (const a of items) {
const date = a.exifInfo?.dateTimeOriginal || a.fileCreatedAt;
map.set(a.id, { id: a.id, name: a.originalFileName, date });
}
const next = d.assets.nextPage;
if (!next) break;
page = Number(next);
}
return [...map.values()];
}
// Vilka immich-<assetId>-*.jpg finns redan i repot? → { assetId: filename }
function existingSynced() {
if (!fs.existsSync(PORTFOLIO_DIR)) return {};
const out = {};
for (const f of fs.readdirSync(PORTFOLIO_DIR)) {
const m = f.match(/^immich-([0-9a-f-]{36})-/i);
if (m) out[m[1]] = f;
}
return out;
}
// Bygg destinationsfilnamn: immich-<assetId>-<ÅÅÅÅMMDD>-<safeOriginalName>.jpg
function destName(asset) {
const d = asset.date ? new Date(asset.date) : new Date();
const ymd = `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, "0")}${String(d.getDate()).padStart(2, "0")}`;
// strippa ev. "<assetid>__"-prefix från originalnamnet (från migreringen), behåll basnamn utan ändelse
let base = asset.name.replace(/^[0-9a-f-]{36}__/i, "").replace(/\.[^.]+$/, "");
base = base.replace(/[^\w.\-]/g, "_").slice(0, 60);
return `immich-${asset.id}-${ymd}-${base}.jpg`;
}
async function downloadAndResize(asset, destPath) {
const res = await api("GET", `/assets/${asset.id}/original`);
const buf = Buffer.from(await res.arrayBuffer());
await sharp(buf)
.rotate() // respektera EXIF-orientering
.resize(MAX_DIM, MAX_DIM, { fit: "inside", withoutEnlargement: true })
.withMetadata() // BEVARA EXIF (kritiskt för portfolions datum/kamera)
.jpeg({ quality: JPEG_QUALITY })
.toFile(destPath);
}
async function main() {
const taggedAll = await fetchTagged();
// Hoppa över RAW-filer elegant — de räknas inte mot synk (tagga JPEG-versionen istället)
const skippedRaw = taggedAll.filter((a) => isRaw(a.name));
const tagged = taggedAll.filter((a) => !isRaw(a.name));
const synced = existingSynced();
const taggedIds = new Set(tagged.map((a) => a.id));
const toAdd = tagged.filter((a) => !synced[a.id]);
const toRemove = Object.entries(synced).filter(([id]) => !taggedIds.has(id)).map(([id, file]) => ({ id, file }));
console.log(`portfolio-synk: ${taggedAll.length} taggade (${tagged.length} bilder + ${skippedRaw.length} RAW), ${Object.keys(synced).length} redan synkade`);
console.log(`→ lägg till: ${toAdd.length}, ta bort: ${toRemove.length}`);
if (skippedRaw.length) {
console.log(`⏭ Hoppade över ${skippedRaw.length} RAW-fil(er) — tagga JPEG-versionen istället:`);
for (const r of skippedRaw) console.log(` ${r.name}`);
}
fs.mkdirSync(PORTFOLIO_DIR, { recursive: true });
for (const a of toAdd) {
const fname = destName(a);
const dest = path.join(PORTFOLIO_DIR, fname);
try {
await downloadAndResize(a, dest);
console.log(` + ${fname}`);
} catch (e) {
console.error(` ! misslyckades ${a.name}: ${e.message}`);
process.exitCode = 1; // signalera fel men fortsätt med resten
}
}
for (const r of toRemove) {
fs.rmSync(path.join(PORTFOLIO_DIR, r.file), { force: true });
console.log(` - ${r.file}`);
}
// skriv ut om något ändrats (workflow läser detta för att avgöra commit)
const changed = toAdd.length > 0 || toRemove.length > 0;
fs.writeFileSync(process.env.GITHUB_OUTPUT || "/dev/stdout",
`changed=${changed}\nadded=${toAdd.length}\nremoved=${toRemove.length}\n`, { flag: "a" });
}
main().catch((e) => { console.error("FEL:", e.message); process.exit(1); });
Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1010 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1000 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 861 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 705 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 728 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 986 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 742 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 991 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 895 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 836 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 797 KiB

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