mirror of
https://github.com/linkwarden/linkwarden.git
synced 2026-03-03 03:57:01 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3926e566b7 | ||
|
|
bca333be26 | ||
|
|
02a1e3b455 | ||
|
|
5b0c66b5e2 | ||
|
|
7c0c823c41 | ||
|
|
a8d2c55d12 | ||
|
|
37410fcf97 | ||
|
|
0ab4a2d883 | ||
|
|
756b896fe6 | ||
|
|
e3e3611b54 | ||
|
|
4bf65f8ebd | ||
|
|
6956c71aa2 |
14
.github/FUNDING.yml
vendored
14
.github/FUNDING.yml
vendored
@@ -1,13 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: linkwarden
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
github: daniel31x13
|
||||
buy_me_a_coffee: daniel31x13
|
||||
67
README.md
67
README.md
@@ -38,32 +38,49 @@ Linkwarden is also designed with collaboration in mind, enabling you to share li
|
||||
|
||||
## Features
|
||||
|
||||
- 📸 Auto capture a screenshot, PDF, and single html file of each webpage.
|
||||
- 📖 Reader view of the webpage, with the ability to highlight and annotate text.
|
||||
- 🏛️ Send your webpage to Wayback Machine ([archive.org](https://archive.org)) for a snapshot. (Optional)
|
||||
- ✨ Local AI Tagging to automatically tag your links based on their content (Optional).
|
||||
- 📂 Organize links by collection, sub-collection, name, description and multiple tags.
|
||||
- 👥 Collaborate on gathering links in a collection.
|
||||
- 🎛️ Customize the permissions of each member.
|
||||
- 🌐 Share your collected links and preserved formats with the world.
|
||||
- 📌 Pin your favorite links to dashboard.
|
||||
- 🔍 Full text search, filter and sort for easy retrieval.
|
||||
- 📱 Responsive design and supports most modern browsers.
|
||||
- 🌓 Dark/Light mode support.
|
||||
- 🧩 Browser extension. [Star it here!](https://github.com/linkwarden/browser-extension)
|
||||
- 📸 Auto capture a screenshot, PDF, and single html file of each webpage
|
||||
- 📖 Reader view of the webpage, with the ability to highlight and annotate text
|
||||
- 🏛️ Send your webpage to Wayback Machine ([archive.org](https://archive.org)) for a snapshot (optional)
|
||||
- ✨ Local AI Tagging to automatically tag your links based on their content (optional)
|
||||
- 📂 Organize links by collection, sub-collection, name, description and multiple tags
|
||||
- 👥 Collaborate on gathering links in a collection
|
||||
- 🎛️ Customize the permissions of each member
|
||||
- 🌐 Share your collected links and preserved formats with the world
|
||||
- 📱 Native iOS and android mobile apps
|
||||
- 🔍 Full text search, filter and sort for easy retrieval
|
||||
- 🌓 Dark/Light mode support
|
||||
- 🧩 Browser extension (star it [here](https://github.com/linkwarden/browser-extension)!)
|
||||
- 🔄 Browser Synchronization (using [Floccus](https://floccus.org)!)
|
||||
- ⬇️ Import and export your bookmarks.
|
||||
- 🔐 SSO integration. (Enterprise and Self-hosted users only)
|
||||
- 📦 Installable Progressive Web App (PWA).
|
||||
- 🍎 iOS Shortcut to save Links to Linkwarden.
|
||||
- 🔑 API keys.
|
||||
- ✅ Bulk actions.
|
||||
- 👥 User administration.
|
||||
- 🌐 Support for Other Languages (i18n).
|
||||
- 📁 Image and PDF Uploads.
|
||||
- 🎨 Custom Icons for Links and Collections.
|
||||
- 🔔 RSS Feed Subscription.
|
||||
- ✨ And many more features. (Literally!)
|
||||
- ⬆️ Upload from SingleFile (check out the [guide](https://docs.linkwarden.app/Usage/upload-from-singlefile))
|
||||
- 🔐 SSO integration (Enterprise and Self-hosted users only)
|
||||
- 🍎 iOS Shortcut to save links to Linkwarden
|
||||
- 🔑 API keys
|
||||
- ✅ Bulk actions
|
||||
- 👥 User administration
|
||||
- 🌐 Support for other languages (i18n)
|
||||
- 📁 Image and PDF uploads
|
||||
- 🎨 Custom icons for links and collections
|
||||
- 🔔 RSS feed subscription
|
||||
- ✨ And many more features (literally!)
|
||||
|
||||
## Get Our Official Mobile App
|
||||
|
||||
<img src="./assets/mobile_apps.png" alt="Different screens (iPad, Pixel, and iPhone)" width="400" />
|
||||
|
||||
> [!IMPORTANT]
|
||||
> To use the app you’ll first need a Linkwarden account.
|
||||
|
||||
To create an account, you can choose between:
|
||||
|
||||
- [**Linkwarden Cloud**](https://linkwarden.app/#pricing) – instant setup, and your subscription directly supports ongoing development.
|
||||
- [**Self-hosted Linkwarden**](https://docs.linkwarden.app/self-hosting/installation) – free, but you’ll need to deploy and maintain a Linkwarden instance on a server.
|
||||
|
||||
After creating an account, download the app from your preferred store:
|
||||
|
||||
[](https://apps.apple.com/app/linkwarden/id6752550960)
|
||||
[](https://play.google.com/store/apps/details?id=app.linkwarden)
|
||||
|
||||
(To get the app as an APK outside Google Play, check out our [builds](https://github.com/linkwarden/builds) repository.)
|
||||
|
||||
## Like what we're doing? Give us a Star ⭐
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ export default async function getLatestVersion(setShowAnnouncement: Function) {
|
||||
const latestMessage = data.message;
|
||||
|
||||
if (
|
||||
announcementId !== latestAnnouncement ||
|
||||
announcementMessage !== latestMessage
|
||||
announcementId != latestAnnouncement ||
|
||||
announcementMessage != latestMessage
|
||||
) {
|
||||
setShowAnnouncement(true);
|
||||
if (latestAnnouncement)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@linkwarden/web",
|
||||
"version": "v2.13.3",
|
||||
"version": "v2.13.5",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/linkwarden/linkwarden.git",
|
||||
"author": "Daniel31X13 <daniel31x13@gmail.com>",
|
||||
|
||||
@@ -393,75 +393,75 @@
|
||||
"saved": "Salvato",
|
||||
"untitled": "Senza titolo",
|
||||
"no_tags": "Nessun tag.",
|
||||
"no_description_provided": "No description provided.",
|
||||
"change_icon": "Change Icon",
|
||||
"upload_banner": "Upload Banner",
|
||||
"columns": "Columns",
|
||||
"no_description_provided": "Nessuna descrizione fornita.",
|
||||
"change_icon": "Cambia Icona",
|
||||
"upload_banner": "Carica Grafica",
|
||||
"columns": "Colonne",
|
||||
"default": "Predefinito",
|
||||
"invalid_url_guide": "Please enter a valid Address for the Link. (It should start with http/https)",
|
||||
"email_invalid": "Please enter a valid email address.",
|
||||
"username_invalid_guide": "Username has to be at least 3 characters, no spaces and special characters are allowed.",
|
||||
"team_management": "Team Management",
|
||||
"invite_user": "Invite User",
|
||||
"invite_users": "Invite Users",
|
||||
"invite_user_desc": "To invite someone to your team, please enter their email address below:",
|
||||
"invalid_url_guide": "Inserisci un Indirizzo valido per il Collegamento. (Dovrebbe iniziare con http/https)",
|
||||
"email_invalid": "Inserisci un indirizzo email valido.",
|
||||
"username_invalid_guide": "Il nome utente deve contenere almeno 3 caratteri, non sono ammessi spazi e caratteri speciali.",
|
||||
"team_management": "Gestione Team",
|
||||
"invite_user": "Invita Utente",
|
||||
"invite_users": "Invita Utenti",
|
||||
"invite_user_desc": "Per invitare qualcuno nel tuo team, inserisci il suo indirizzo email qui sotto:",
|
||||
"invite_user_note": "Please note that once the invitation is accepted, an additional seat will be purchased and your account will automatically be billed for this addition.",
|
||||
"invite_user_price": "The cost of each seat is ${{price}} per month or ${{priceAnnual}} per year, depending on your current subscription plan.",
|
||||
"send_invitation": "Send Invitation",
|
||||
"learn_more": "Learn more",
|
||||
"invite_user_price": "Il costo di ogni postazione è di ${{price}} al mese o ${{priceAnnual}} all'anno, a seconda del tuo attuale piano di abbonamento.",
|
||||
"send_invitation": "Invia Invito",
|
||||
"learn_more": "Ulteriori informazioni",
|
||||
"invitation_desc": "{{owner}} ti ha invitato a unirti a Linkwarden. \nPer continuare, per favore completa la configurazione del tuo account.",
|
||||
"invitation_accepted": "Invitation Accepted!",
|
||||
"status": "Status",
|
||||
"pending": "Pending",
|
||||
"active": "Active",
|
||||
"manage_seats": "Manage Seats",
|
||||
"invitation_accepted": "Invito Accettato!",
|
||||
"status": "Stato",
|
||||
"pending": "In Attesa",
|
||||
"active": "Attivo",
|
||||
"manage_seats": "Gestisci Postazioni",
|
||||
"seats_purchased": "{{count}} posti acquistati",
|
||||
"seat_purchased": "{{count}} seat purchased",
|
||||
"date_added": "Date Added",
|
||||
"resend_invite": "Resend Invitation",
|
||||
"resend_invite_success": "Invitation Resent!",
|
||||
"remove_user": "Remove User",
|
||||
"continue_to_dashboard": "Continue to Dashboard",
|
||||
"confirm_user_removal_desc": "They will need to have a subscription to access Linkwarden again.",
|
||||
"click_out_to_apply": "Click outside to apply",
|
||||
"submit": "Submit",
|
||||
"thanks_for_feedback": "Thanks for your feedback!",
|
||||
"quick_survey": "Quick Survey",
|
||||
"seat_purchased": "{{count}} postazioni acquistate",
|
||||
"date_added": "Data Aggiunta",
|
||||
"resend_invite": " Reinvia Invito",
|
||||
"resend_invite_success": "Invito Reinviato!",
|
||||
"remove_user": "Rimuovi Utente",
|
||||
"continue_to_dashboard": "Continua alla Dashboard",
|
||||
"confirm_user_removal_desc": "Dovranno sottoscrivere un abbonamento per accedere nuovamente a Linkwarden.",
|
||||
"click_out_to_apply": "Fai clic all'esterno per applicare",
|
||||
"submit": "Invia",
|
||||
"thanks_for_feedback": "Grazie per il tuo feedback!",
|
||||
"quick_survey": "Sondaggio Rapido",
|
||||
"how_did_you_discover_linkwarden": "Come hai scoperto Linkwarden?",
|
||||
"rather_not_say": "Rather not say",
|
||||
"search_engine": "Search Engine (Google, Bing, etc.)",
|
||||
"rather_not_say": "Preferisco non specificarlo",
|
||||
"search_engine": "Motore di Ricerca (Google, Bing, ecc.)",
|
||||
"reddit": "Reddit",
|
||||
"lemmy": "Lemmy",
|
||||
"people_recommendation": "Recommendation (Friend, Family, etc.)",
|
||||
"open_all_links": "Open all Links",
|
||||
"people_recommendation": "Raccomandazione (Amico, Famiglia, etc.)",
|
||||
"open_all_links": "Apri tutti i Link",
|
||||
"ai_settings": "Impostazioni IA",
|
||||
"generate_tags_for_existing_links": "Generate tags for existing Links",
|
||||
"generate_tags_for_existing_links": "Genera tag per i Link esistenti",
|
||||
"ai_tagging_method": "AI Tagging Method:",
|
||||
"based_on_predefined_tags": "Based on predefined Tags",
|
||||
"based_on_predefined_tags_desc": "Auto-categorize links to predefined tags based on the content of each link.",
|
||||
"based_on_predefined_tags_desc": "Categorizza automaticamente i link in tag predefiniti in base al contenuto di ciascun link.",
|
||||
"based_on_existing_tags": "Based on existing Tags",
|
||||
"based_on_existing_tags_desc": "Auto-categorize links to existing tags based on the content of each link.",
|
||||
"based_on_existing_tags_desc": "Categorizza automaticamente i link in tag esistenti in base al contenuto di ciascun link.",
|
||||
"auto_generate_tags": "Auto-generate Tags",
|
||||
"auto_generate_tags_desc": "Auto-generate relevant tags based on the content of each link.",
|
||||
"auto_generate_tags_desc": "Genera automaticamente tag pertinenti in base al contenuto di ogni link.",
|
||||
"disabled": "Disabilitato",
|
||||
"ai_tagging_disabled_desc": "AI tagging is disabled.",
|
||||
"tag_selection_placeholder": "Choose or add custom tags…",
|
||||
"rss_subscriptions": "RSS Subscriptions",
|
||||
"rss_subscriptions_desc": "RSS Subscriptions are a way to keep up with your favorite websites and blogs. Linkwarden will automatically fetch the latest articles every {{number}} minutes from the feeds you provide.",
|
||||
"rss_subscriptions_desc": "Le iscrizioni ai feed RSS sono un modo per rimanere aggiornati sui tuoi siti web e blog preferiti. Linkwarden recupererà automaticamente gli ultimi articoli ogni {{number}} minuti dai feed da te forniti.",
|
||||
"rss_deletion_confirmation": "Are you sure you want to delete this RSS Subscription?",
|
||||
"new_rss_subscription": "New RSS Subscription",
|
||||
"rss_subscription_deleted": "RSS Subscription deleted!",
|
||||
"create_rss_subscription": "Create RSS Subscription",
|
||||
"rss_feed": "Feed RSS",
|
||||
"pinned_links": "Pinned Links",
|
||||
"recent_links": "Recent Links",
|
||||
"pinned_links": "Link Fissati",
|
||||
"recent_links": "Link Recenti",
|
||||
"search_results": "Search Results",
|
||||
"linkwarden_icon": "Icona Linkwarden",
|
||||
"permanent_session": "This is a permanent session",
|
||||
"locale": "en-US",
|
||||
"not_found_404": "404 - Not Found",
|
||||
"collection_publicly_shared": "Questa collezione è condivisa pubblicamente.",
|
||||
"search_for_links": "Search for Links",
|
||||
"search_for_links": "Cerca per Link",
|
||||
"search_query_invalid_symbol": "The search query should not contain '%'.",
|
||||
"open_modal_new_tab": "Open this modal in a new tab",
|
||||
"file": "File",
|
||||
|
||||
@@ -494,36 +494,36 @@
|
||||
"refresh_multiple_preserved_formats_confirmation_desc": "現在保存されている形式を削除し、 {{count}} リンクを再保存します。",
|
||||
"refresh_preserved_formats_confirmation_desc": "現在保存されている形式を削除し、このリンクを再保存します。",
|
||||
"tag_already_added": "このタグは既に追加されています。",
|
||||
"all_tags": "All Tags",
|
||||
"new_tag": "New Tag",
|
||||
"create_new_tag": "Create New Tag",
|
||||
"tag_deletion_confirmation_message": "Are you sure you want to delete this Tag?",
|
||||
"delete_tags_by_number_of_links": "Delete Tags with <0/> Links",
|
||||
"delete_all_tags": "Delete all Tags",
|
||||
"bulk_delete_tags": "Bulk Delete Tags",
|
||||
"count_tags_deleted": "{{count}} Tags Deleted",
|
||||
"count_tag_deleted": "{{count}} Tag Deleted",
|
||||
"tag_name_placeholder": "e.g. Technology",
|
||||
"link_count_high_low": "Link count (high to low)",
|
||||
"link_count_low_high": "Link count (low to high)",
|
||||
"tags_selected": "{{count}} Tags selected",
|
||||
"tag_selected": "1 Tag selected",
|
||||
"merge_tags": "Merge Tags",
|
||||
"merge_count_tags": "Merge {{count}} Tags",
|
||||
"rename_tag_instruction": "Please provide a name for the final tag.",
|
||||
"merging": "Merging...",
|
||||
"delete_tags": "Delete {{count}} Tags",
|
||||
"tags_deletion_confirmation_message": "Are you sure you want to delete {{count}} Tags? This will remove the tags from all links.",
|
||||
"subscribe_later": "Subscribe Later?",
|
||||
"create_your_first_tag": "Create Your First Tag!",
|
||||
"create_your_first_tag_desc": "Tags help you categorize and find your Links easily. You can create Tags based on topics, projects, or any system that works for you.",
|
||||
"create_your_first_collection": "Create Your First Collection!",
|
||||
"create_your_first_collection_desc": "Collections are like folders for your Links which can then be shared with others.",
|
||||
"this_tag_has_no_links": "This Tag Has No Links",
|
||||
"this_tag_has_no_links_desc": "Use this Tag while creating or editing Links!",
|
||||
"accept_promotional_emails": "Get notified about new features and offers via email.",
|
||||
"expand_sidebar": "Expand Sidebar",
|
||||
"shrink_sidebar": "Shrink Sidebar",
|
||||
"trial_left_plural": "Trial ends in {{count}} days. Subscribe.",
|
||||
"trial_left_singular": "Trial ends in 1 day. Subscribe."
|
||||
"all_tags": "すべてのタグ",
|
||||
"new_tag": "新しいタグ",
|
||||
"create_new_tag": "新しいタグを作成",
|
||||
"tag_deletion_confirmation_message": "このタグを削除しますか?",
|
||||
"delete_tags_by_number_of_links": "<0/>リンクを含むタグを削除",
|
||||
"delete_all_tags": "すべてのタグを削除",
|
||||
"bulk_delete_tags": "タグを一括削除",
|
||||
"count_tags_deleted": "{{count}} 個のタグが削除されました",
|
||||
"count_tag_deleted": "{{count}} 個のタグが削除されました",
|
||||
"tag_name_placeholder": "例: テクノロジー",
|
||||
"link_count_high_low": "リンク数(高から低)",
|
||||
"link_count_low_high": "リンク数(低から高)",
|
||||
"tags_selected": "{{count}} 個のタグが選択されました",
|
||||
"tag_selected": "1 個のタグが選択されました",
|
||||
"merge_tags": "タグをマージする",
|
||||
"merge_count_tags": "{{count}} 件のタグをマージ",
|
||||
"rename_tag_instruction": "最終的なタグの名前を入力してください。",
|
||||
"merging": "マージ中…",
|
||||
"delete_tags": "{{count}} 件のタグを削除",
|
||||
"tags_deletion_confirmation_message": "{{count}} 件のタグを削除してもよろしいですか?この操作によりすべてのリンクからタグが削除されます。",
|
||||
"subscribe_later": "後で申し込みますか?",
|
||||
"create_your_first_tag": "最初のタグを作成しよう!",
|
||||
"create_your_first_tag_desc": "タグはリンクの分類や検索を容易にします。トピックやプロジェクトなど、あなたにとって使いやすい体系でタグを作成できます。",
|
||||
"create_your_first_collection": "最初のコレクションを作しよう!",
|
||||
"create_your_first_collection_desc": "コレクションはリンクをまとめるフォルダのような機能で、他のユーザーと共有できます。",
|
||||
"this_tag_has_no_links": "このタグにはリンクがありません",
|
||||
"this_tag_has_no_links_desc": "リンクの作成時や編集時にこのタグを使用してください!",
|
||||
"accept_promotional_emails": "新機能やお得な情報をメールでお知らせします。",
|
||||
"expand_sidebar": "サイドバーを展開",
|
||||
"shrink_sidebar": "サイドバーを縮小",
|
||||
"trial_left_plural": "お試し期間は {{count}} 日で終了します。登録してください。",
|
||||
"trial_left_singular": "試用期間はあと 1 日で終了します。登録してください。"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
predefinedTagsPrompt,
|
||||
} from "./prompts";
|
||||
import { prisma } from "@linkwarden/prisma";
|
||||
import { generateObject } from "ai";
|
||||
import { generateText } from "ai";
|
||||
import { LanguageModelV2 } from "@ai-sdk/provider";
|
||||
import {
|
||||
createOpenAICompatible,
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
} from "@ai-sdk/openai-compatible";
|
||||
import { perplexity } from "@ai-sdk/perplexity";
|
||||
import { azure } from "@ai-sdk/azure";
|
||||
import { z } from "zod";
|
||||
import { anthropic } from "@ai-sdk/anthropic";
|
||||
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
|
||||
import { createOllama } from "ollama-ai-provider-v2";
|
||||
@@ -127,15 +126,13 @@ export default async function autoTagLink(
|
||||
return console.log("No predefined tags to auto tag for link: ", link.url);
|
||||
}
|
||||
|
||||
const { object } = await generateObject({
|
||||
const { text } = await generateText({
|
||||
model: getAIModel(),
|
||||
prompt: prompt,
|
||||
output: "array",
|
||||
schema: z.string(),
|
||||
});
|
||||
|
||||
try {
|
||||
let tags = object;
|
||||
let tags: string[] = JSON.parse(text);
|
||||
|
||||
if (!tags || tags.length === 0) {
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const generateTagsPrompt = (text: string) => `
|
||||
You are a Bookmark Manager that should extract relevant tags from the following text, here are the rules:
|
||||
- The final output should be only an array of tags (like ["tag1", "tag2", "...").
|
||||
- The final output should be only an array of tags (like ["tag1", "tag2", "..."]).
|
||||
- The tags should be in the language of the text.
|
||||
- The maximum number of tags is 5.
|
||||
- Each tag should be maximum one to two words.
|
||||
@@ -15,7 +15,7 @@ export const predefinedTagsPrompt = (text: string, tags: string[]) => `
|
||||
You are a Bookmark Manager that should match the following text with predefined tags.
|
||||
Predefined tags: ${tags.join(", ")}.
|
||||
Here are the rules:
|
||||
- The final output should be only an array of tags (like ["tag1", "tag2", "...").
|
||||
- The final output should be only an array of tags (like ["tag1", "tag2", "..."]).
|
||||
- The tags should be in the language of the text.
|
||||
- The maximum number of tags is 5.
|
||||
- Each tag should be maximum one to two words.
|
||||
@@ -30,7 +30,7 @@ export const existingTagsPrompt = (text: string, tags: string[]) => `
|
||||
You are a Bookmark Manager that should match the following text with existing tags.
|
||||
The existing tags are sorted from most used to least used: ${tags.join(", ")}.
|
||||
Here are the rules:
|
||||
- The final output should be only an array of tags (like ["tag1", "tag2", "...").
|
||||
- The final output should be only an array of tags (like ["tag1", "tag2", "..."]).
|
||||
- The tags should be in the language of the text.
|
||||
- The maximum number of tags is 5.
|
||||
- Each tag should be maximum one to two words.
|
||||
|
||||
BIN
assets/app_store.png
Normal file
BIN
assets/app_store.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
BIN
assets/google_play.png
Normal file
BIN
assets/google_play.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
BIN
assets/home.png
BIN
assets/home.png
Binary file not shown.
|
Before Width: | Height: | Size: 776 KiB After Width: | Height: | Size: 606 KiB |
BIN
assets/mobile_apps.png
Normal file
BIN
assets/mobile_apps.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
Reference in New Issue
Block a user