Merge pull request #566 from plebbit/development

Development
This commit is contained in:
Tom (plebeius.eth)
2024-10-14 12:55:24 +02:00
committed by GitHub
66 changed files with 653 additions and 342 deletions
+93
View File
@@ -0,0 +1,93 @@
# send notifications to telegram group on commits, releases, issues
name: notifications
on:
pull_request:
branches:
- master
# push:
# branches:
# - master
release:
types: [published]
issues:
types: [opened]
jobs:
# push:
# if: ${{ github.event_name == 'push' }}
# runs-on: ubuntu-latest
# strategy:
# matrix:
# commit: ${{ github.event.commits }}
# steps:
# # - name: debug
# # env:
# # DEBUG: ${{ toJSON(matrix.commit) }}
# # run: echo "$DEBUG"
# # write message to file
# - run: echo "<code>${{ matrix.commit.message }}</code>" >> message.txt
# - run: echo "" >> message.txt
# - run: echo "by <i>${{ matrix.commit.author.username }}</i>" >> message.txt
# - run: echo "${{ matrix.commit.url }}" >> message.txt
# - run: date -d "${{ matrix.commit.timestamp }}" +"%d/%m/%y at %H:%M" >> message.txt
# # send message, @plebbit telegram chat id is -1001665335693
# - name: "telegram notification"
# uses: appleboy/telegram-action@master
# with:
# to: -1001665335693
# token: ${{ secrets.TELEGRAM_TOKEN }}
# # commit links don't show anything useful in preview
# disable_web_page_preview: true
# format: html
# message_file: message.txt
release:
if: ${{ github.event_name == 'release' }}
runs-on: ubuntu-latest
steps:
# - name: debug
# env:
# DEBUG: ${{ toJSON(github) }}
# run: echo "$DEBUG"
# write message to file
- run: echo "<b>${{ github.event.repository.name }} ${{ github.event.release.name }}</b>" >> message.txt
- run: echo "" >> message.txt
- run: echo "${{ github.event.release.body }}" >> message.txt
- run: echo "${{ github.event.release.html_url }}" >> message.txt
# send message, @plebbit telegram chat id is -1001665335693
- name: "telegram notification"
uses: appleboy/telegram-action@master
with:
to: -1001665335693
token: ${{ secrets.TELEGRAM_TOKEN }}
format: html
message_file: message.txt
issue:
if: ${{ github.event_name == 'issues' }}
runs-on: ubuntu-latest
steps:
# - name: debug
# env:
# DEBUG: ${{ toJSON(github) }}
# run: echo "$DEBUG"
# write message to file
- run: echo "<code>${{ github.event.issue.title }}</code>" >> message.txt
- run: echo "" >> message.txt
- run: echo "by <i>${{ github.event.issue.user.login }}</i>" >> message.txt
- run: echo "${{ github.event.issue.html_url }}" >> message.txt
# send message, @plebbit telegram chat id is -1001665335693
- name: "telegram notification"
uses: appleboy/telegram-action@master
with:
to: -1001665335693
token: ${{ secrets.TELEGRAM_TOKEN }}
format: html
message_file: message.txt
+2
View File
@@ -1,6 +1,8 @@
# plebbit temp files
.plebbit
bin
.env
.deploy-env
# Logs
logs
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="2d2b4f7a-62f7-4401-a08a-8502f60bf3e0" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="TaskManager">
<servers />
</component>
</project>
+6 -1
View File
@@ -1,6 +1,7 @@
apply plugin: 'com.android.application'
android {
namespace "plebchan.android"
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "plebchan.android"
@@ -24,6 +25,9 @@ android {
}
repositories {
google()
mavenCentral()
maven { url "https://maven.google.com" }
flatDir{
dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
}
@@ -33,10 +37,11 @@ dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
implementation project(':capacitor-android')
implementation project(':capacitor-cordova-android-plugins')
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
implementation project(':capacitor-cordova-android-plugins')
implementation "org.apache.cordova:framework:$cordovaAndroidVersion"
}
apply from: 'capacitor.build.gradle'
+3 -2
View File
@@ -2,14 +2,15 @@
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
implementation project(':capacitor-app')
implementation project(':capacitor-device')
}
+3 -4
View File
@@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="plebchan.android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
@@ -15,7 +13,8 @@
android:name="plebchan.android.MainActivity"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBarLaunch"
android:launchMode="singleTask">
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -2,5 +2,10 @@
"appId": "plebchan.android",
"appName": "plebchan",
"webDir": "build",
"bundledWebRuntime": false
"bundledWebRuntime": false,
"plugins": {
"Device": {
"lazyLoad": true
}
}
}
@@ -2,5 +2,9 @@
{
"pkg": "@capacitor/app",
"classpath": "com.capacitorjs.plugins.app.AppPlugin"
},
{
"pkg": "@capacitor/device",
"classpath": "com.capacitorjs.plugins.device.DevicePlugin"
}
]
+3 -3
View File
@@ -4,10 +4,10 @@ buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.1'
classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'com.google.gms:google-services:4.3.5'
// NOTE: Do not place your application dependencies here; they belong
@@ -20,7 +20,7 @@ apply from: "variables.gradle"
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
+3
View File
@@ -4,3 +4,6 @@ project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/
include ':capacitor-app'
project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android')
include ':capacitor-device'
project(':capacitor-device').projectDir = new File('../node_modules/@capacitor/device/android')
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+5 -5
View File
@@ -1,7 +1,7 @@
ext {
minSdkVersion = 21
compileSdkVersion = 30
targetSdkVersion = 30
minSdkVersion = 22
compileSdkVersion = 33
targetSdkVersion = 33
androidxActivityVersion = '1.2.0'
androidxAppCompatVersion = '1.2.0'
androidxCoordinatorLayoutVersion = '1.1.0'
@@ -10,5 +10,5 @@ ext {
junitVersion = '4.13.1'
androidxJunitVersion = '1.1.2'
androidxEspressoCoreVersion = '3.3.0'
cordovaAndroidVersion = '7.0.0'
}
cordovaAndroidVersion = '10.1.1'
}
+6 -1
View File
@@ -4,7 +4,12 @@ const config: CapacitorConfig = {
appId: 'plebchan.android',
appName: 'plebchan',
webDir: 'build',
bundledWebRuntime: false
bundledWebRuntime: false,
plugins: {
Device: {
lazyLoad: true,
},
},
};
export default config;
+4 -3
View File
@@ -7,6 +7,7 @@
"private": true,
"dependencies": {
"@capacitor/app": "1.1.1",
"@capacitor/device": "6.0.1",
"@floating-ui/react": "0.26.1",
"@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#a80ef4b155abf119e66c019576cbc1b338390e00",
"@testing-library/jest-dom": "5.14.1",
@@ -85,9 +86,9 @@
]
},
"devDependencies": {
"@capacitor/android": "3.6.0",
"@capacitor/cli": "3.6.0",
"@capacitor/core": "3.6.0",
"@capacitor/android": "5.0.0",
"@capacitor/cli": "5.0.0",
"@capacitor/core": "5.0.0",
"@types/memoizee": "0.4.9",
"concurrently": "8.0.1",
"conventional-changelog-cli": "4.1.0",
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "لا يمكن نشر تعليق فارغ.",
"more_posts_last_week": "تظهر المشاركات منذ {{currentTimeFilterName}} ، <1>عرض المزيد من المشاركات من الأسبوع الماضي</1>",
"more_posts_last_month": "تظهر المشاركات منذ {{currentTimeFilterName}} ، <1>عرض المزيد من المشاركات من الشهر الماضي</1>",
"newer_posts_available": "مشاركات جديدة متاحة، <1>قم بتحديث الخلاصة</1>"
"newer_posts_available": "مشاركات جديدة متاحة، <1>قم بتحديث الخلاصة</1>",
"stored_locally": "مخزنة محليًا ({{location}})، ليست متزامنة عبر الأجهزة",
"choose_one": "اختر واحدة:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "খালি মন্তব্য পোস্ট করা যাবে না।",
"more_posts_last_week": "আপনি {{currentTimeFilterName}} থেকে পোস্টগুলি দেখছেন, <1>গত সপ্তাহ থেকে আরও পোস্ট দেখান</1>",
"more_posts_last_month": "আপনি {{currentTimeFilterName}} থেকে পোস্টগুলি দেখছেন, <1>গত মাস থেকে আরও পোস্ট দেখান</1>",
"newer_posts_available": "নতুন পোস্ট উপলব্ধ, <1>ফিডটি রিফ্রেশ করুন</1>"
"newer_posts_available": "নতুন পোস্ট উপলব্ধ, <1>ফিডটি রিফ্রেশ করুন</1>",
"stored_locally": "স্থানীয়ভাবে সংরক্ষিত ({{location}}), ডিভাইসের মধ্যে সিঙ্ক করা হয়নি",
"choose_one": "একটি নির্বাচন করুন:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Nelze publikovat prázdný komentář.",
"more_posts_last_week": "Zobrazujeme příspěvky od {{currentTimeFilterName}}, <1>zobrazit další příspěvky z minulého týdne</1>",
"more_posts_last_month": "Zobrazujeme příspěvky od {{currentTimeFilterName}}, <1>zobrazit další příspěvky z minulého měsíce</1>",
"newer_posts_available": "Novější příspěvky jsou k dispozici, <1>aktualizujte kanál</1>"
"newer_posts_available": "Novější příspěvky jsou k dispozici, <1>aktualizujte kanál</1>",
"stored_locally": "Uloženo lokálně ({{location}}), není synchronizováno mezi zařízeními",
"choose_one": "Vyberte jednu:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Kan ikke poste en tom kommentar.",
"more_posts_last_week": "Viser indlæg siden {{currentTimeFilterName}}, <1>vis flere indlæg fra sidste uge</1>",
"more_posts_last_month": "Viser indlæg siden {{currentTimeFilterName}}, <1>vis flere indlæg fra sidste måned</1>",
"newer_posts_available": "Nyere indlæg tilgængelige, <1>genindlæs feed</1>"
"newer_posts_available": "Nyere indlæg tilgængelige, <1>genindlæs feed</1>",
"stored_locally": "Lager lokalt ({{location}}), ikke synkroniseret på tværs af enheder",
"choose_one": "Vælg en:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Kann keinen leeren Kommentar posten.",
"more_posts_last_week": "Zeigt Beiträge seit {{currentTimeFilterName}}, <1>zeige mehr Beiträge aus der letzten Woche</1>",
"more_posts_last_month": "Zeigt Beiträge seit {{currentTimeFilterName}}, <1>zeige mehr Beiträge aus dem letzten Monat</1>",
"newer_posts_available": "Neuere Beiträge verfügbar, <1>Feed neu laden</1>"
"newer_posts_available": "Neuere Beiträge verfügbar, <1>Feed neu laden</1>",
"stored_locally": "Lokal gespeichert ({{location}}), nicht geräteübergreifend synchronisiert",
"choose_one": "Wählen Sie eine:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Δεν μπορεί να δημοσιευτεί κενό σχόλιο.",
"more_posts_last_week": "Εμφανίζονται αναρτήσεις από {{currentTimeFilterName}}, <1>εμφάνιση περισσότερων αναρτήσεων από την περασμένη εβδομάδα</1>",
"more_posts_last_month": "Διατίθενται αναρτήσεις από {{currentTimeFilterName}}, <1>εμφάνιση περισσότερων αναρτήσεων από τον περασμένο μήνα</1>",
"newer_posts_available": "Διατίθενται νεότερες δημοσιεύσεις, <1>επανεκκινήστε τη ροή</1>"
"newer_posts_available": "Διατίθενται νεότερες δημοσιεύσεις, <1>επανεκκινήστε τη ροή</1>",
"stored_locally": "Αποθηκευμένο τοπικά ({{location}}), δεν συγχρονίζεται σε όλες τις συσκευές",
"choose_one": "Επιλέξτε μία:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Cannot post empty comment.",
"more_posts_last_week": "Showing posts since {{currentTimeFilterName}}, <1>show more posts from last week</1>",
"more_posts_last_month": "Showing posts since {{currentTimeFilterName}}, <1>show more posts from last month</1>",
"newer_posts_available": "Newer posts available, <1>reload feed</1>"
"newer_posts_available": "Newer posts available, <1>reload feed</1>",
"stored_locally": "Stored locally ({{location}}), not synced across devices",
"choose_one": "Choose one:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "No se puede publicar un comentario vacío.",
"more_posts_last_week": "Mostrando publicaciones desde {{currentTimeFilterName}}, <1>mostrar más publicaciones de la semana pasada</1>",
"more_posts_last_month": "Mostrando publicaciones desde {{currentTimeFilterName}}, <1>mostrar más publicaciones del mes pasado</1>",
"newer_posts_available": "Nuevas publicaciones disponibles, <1>recargar el feed</1>"
"newer_posts_available": "Nuevas publicaciones disponibles, <1>recargar el feed</1>",
"stored_locally": "Almacenado localmente ({{location}}), no sincronizado entre dispositivos",
"choose_one": "Elige uno:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "نمی‌توان نظر خالی ارسال کرد.",
"more_posts_last_week": "نمایش پست‌ها از {{currentTimeFilterName}}، <1>نمایش پست‌های بیشتر از هفته گذشته</1>",
"more_posts_last_month": "نمایش پست‌ها از {{currentTimeFilterName}}، <1>نمایش پست‌های بیشتر از ماه گذشته</1>",
"newer_posts_available": "پست‌های جدیدتر در دسترس هستند، <1>بارگذاری مجدد خوراک</1>"
"newer_posts_available": "پست‌های جدیدتر در دسترس هستند، <1>بارگذاری مجدد خوراک</1>",
"stored_locally": "محلی ذخیره شده ({{location}})، با دستگاه‌ها همگام‌سازی نشده است",
"choose_one": "یکی را انتخاب کنید:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Ei voi julkaista tyhjää kommenttia.",
"more_posts_last_week": "Näytetään viestejä ajasta {{currentTimeFilterName}}, <1>näytä lisää viestejä viime viikolta</1>",
"more_posts_last_month": "Näytetään viestejä ajasta {{currentTimeFilterName}}, <1>näytä lisää viestejä viime kuulta</1>",
"newer_posts_available": "Uudemmat viestit saatavilla, <1>lataa syöte uudelleen</1>"
"newer_posts_available": "Uudemmat viestit saatavilla, <1>lataa syöte uudelleen</1>",
"stored_locally": "Tallennettu paikallisesti ({{location}}), ei synkronoitu laitteiden välillä",
"choose_one": "Valitse yksi:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Hindi makapag-post ng walang laman na komento.",
"more_posts_last_week": "Ipinapakita ang mga post mula {{currentTimeFilterName}}, <1>ipakita ang higit pang mga post mula sa nakaraang linggo</1>",
"more_posts_last_month": "Ipinapakita ang mga post mula {{currentTimeFilterName}}, <1>ipakita ang higit pang mga post mula sa nakaraang buwan</1>",
"newer_posts_available": "May mga bagong post na magagamit, <1>i-reload ang feed</1>"
"newer_posts_available": "May mga bagong post na magagamit, <1>i-reload ang feed</1>",
"stored_locally": "Nakaimbak nang lokal ({{location}}), hindi naka-sync sa iba pang device",
"choose_one": "Pumili ng isa:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Impossible de publier un commentaire vide.",
"more_posts_last_week": "Affichage des publications depuis {{currentTimeFilterName}}, <1>afficher plus de publications de la semaine dernière</1>",
"more_posts_last_month": "Affichage des publications depuis {{currentTimeFilterName}}, <1>recharger plus de publications du mois dernier</1>",
"newer_posts_available": "Nouveaux messages disponibles, <1>recharger le fil</1>"
"newer_posts_available": "Nouveaux messages disponibles, <1>recharger le fil</1>",
"stored_locally": "Stocké localement ({{location}}), non synchronisé entre les appareils",
"choose_one": "Choisissez-en un :"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "לא ניתן לפרסם תגובה ריקה.",
"more_posts_last_week": "מראה פוסטים מאז {{currentTimeFilterName}}, <1>הצג פוסטים נוספים מהשבוע שעבר</1>",
"more_posts_last_month": "מראה פוסטים מאז {{currentTimeFilterName}}, <1>הצג פוסטים נוספים מהחודש שעבר</1>",
"newer_posts_available": "ישנם פוסטים חדשים זמינים, <1>טען מחדש את הפיד</1>"
"newer_posts_available": "ישנם פוסטים חדשים זמינים, <1>טען מחדש את הפיד</1>",
"stored_locally": "מאוחסן מקומית ({{location}}), לא מסונכרן בין מכשירים",
"choose_one": "בחר אחת:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "खाली टिप्पणी पोस्ट नहीं कर सकते।",
"more_posts_last_week": "आप {{currentTimeFilterName}} से पोस्ट देख रहे हैं, <1>पिछले सप्ताह के और पोस्ट दिखाएं</1>",
"more_posts_last_month": "आप {{currentTimeFilterName}} से पोस्ट देख रहे हैं, <1>पिछले महीने के और पोस्ट दिखाएं</1>",
"newer_posts_available": "नए पोस्ट उपलब्ध हैं, <1>फीड रीलोड करें</1>"
"newer_posts_available": "नए पोस्ट उपलब्ध हैं, <1>फीड रीलोड करें</1>",
"stored_locally": "स्थानीय रूप से संग्रहीत ({{location}}), उपकरणों के बीच समन्वयित नहीं",
"choose_one": "एक चुनें:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Üres hozzászólást nem lehet közzétenni.",
"more_posts_last_week": "A {{currentTimeFilterName}} óta látható bejegyzések, <1>további bejegyzések megjelenítése az előző héten</1>",
"more_posts_last_month": "A {{currentTimeFilterName}} óta látható bejegyzések, <1>további bejegyzések megjelenítése az előző hónapban</1>",
"newer_posts_available": "Új bejegyzések állnak rendelkezésre, <1>frissítse az adatfolyamot</1>"
"newer_posts_available": "Új bejegyzések állnak rendelkezésre, <1>frissítse az adatfolyamot</1>",
"stored_locally": "Helyben tárolva ({{location}}), nem szinkronizálva eszközök között",
"choose_one": "Válasszon egyet:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Tidak dapat memposting komentar kosong.",
"more_posts_last_week": "Menampilkan pos sejak {{currentTimeFilterName}}, <1>tampilkan lebih banyak pos dari minggu lalu</1>",
"more_posts_last_month": "Menampilkan pos sejak {{currentTimeFilterName}}, <1>tampilkan lebih banyak pos dari bulan lalu</1>",
"newer_posts_available": "Postingan terbaru tersedia, <1>muat ulang umpan</1>"
"newer_posts_available": "Postingan terbaru tersedia, <1>muat ulang umpan</1>",
"stored_locally": "Disimpan secara lokal ({{location}}), tidak disinkronkan antar perangkat",
"choose_one": "Pilih satu:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Impossibile pubblicare un commento vuoto.",
"more_posts_last_week": "Stai visualizzando post da {{currentTimeFilterName}}, <1>visualizza più post della scorsa settimana</1>",
"more_posts_last_month": "Stai visualizzando post da {{currentTimeFilterName}}, <1>visualizza più post del mese scorso</1>",
"newer_posts_available": "Nuovi post disponibili, <1>ricarica il feed</1>"
"newer_posts_available": "Nuovi post disponibili, <1>ricarica il feed</1>",
"stored_locally": "Memorizzato localmente ({{location}}), non sincronizzato tra i dispositivi",
"choose_one": "Scegline una:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "空のコメントは投稿できません。",
"more_posts_last_week": "{{currentTimeFilterName}} からの投稿を表示しています。<1>先週の投稿をさらに表示</1>",
"more_posts_last_month": "{{currentTimeFilterName}} からの投稿を表示しています。<1>先月の投稿をさらに表示</1>",
"newer_posts_available": "新しい投稿が利用可能です、<1>フィードを再読み込み</1>"
"newer_posts_available": "新しい投稿が利用可能です、<1>フィードを再読み込み</1>",
"stored_locally": "ローカルに保存されています ({{location}})、デバイス間で同期されていません",
"choose_one": "いずれかを選択してください:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "빈 댓글을 게시할 수 없습니다.",
"more_posts_last_week": "{{currentTimeFilterName}} 이후의 게시물이 표시됩니다. <1>지난 주의 게시물 더 보기</1>",
"more_posts_last_month": "{{currentTimeFilterName}} 이후의 게시물이 표시됩니다. <1>지난달의 게시물 더 보기</1>",
"newer_posts_available": "새로운 게시물이 있습니다, <1>피드를 새로 고침</1>"
"newer_posts_available": "새로운 게시물이 있습니다, <1>피드를 새로 고침</1>",
"stored_locally": "로컬에 저장됨 ({{location}}), 장치 간에 동기화되지 않음",
"choose_one": "하나를 선택하세요:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "रिक्त टिप्पणी पोस्ट करू शकत नाही.",
"more_posts_last_week": "{{currentTimeFilterName}} पासून पोस्ट दर्शवित आहेत, <1>गेल्या आठवड्यातील अधिक पोस्ट दर्शवा</1>",
"more_posts_last_month": "{{currentTimeFilterName}} पासून पोस्ट दर्शवित आहेत, <1>गेल्या महिन्यातील अधिक पोस्ट दर्शवा</1>",
"newer_posts_available": "नवीनतम पोस्ट उपलब्ध आहेत, <1>फीड रीलोड करा</1>"
"newer_posts_available": "नवीनतम पोस्ट उपलब्ध आहेत, <1>फीड रीलोड करा</1>",
"stored_locally": "स्थानिकपणे संग्रहित ({{location}}), उपकरणांमध्ये समन्वयित केलेले नाही",
"choose_one": "एक निवडा:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Kan geen lege opmerking plaatsen.",
"more_posts_last_week": "Berichten sinds {{currentTimeFilterName}}, <1>meer berichten van afgelopen week tonen</1>",
"more_posts_last_month": "Berichten sinds {{currentTimeFilterName}}, <1>meer berichten van afgelopen maand tonen</1>",
"newer_posts_available": "Nieuwere berichten beschikbaar, <1>herlaad feed</1>"
"newer_posts_available": "Nieuwere berichten beschikbaar, <1>herlaad feed</1>",
"stored_locally": "Lokaal opgeslagen ({{location}}), niet gesynchroniseerd tussen apparaten",
"choose_one": "Kies er een:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Kan ikke poste tom kommentar.",
"more_posts_last_week": "Viser innlegg siden {{currentTimeFilterName}}, <1>vis flere innlegg fra forrige uke</1>",
"more_posts_last_month": "Viser innlegg siden {{currentTimeFilterName}}, <1>vis flere innlegg fra forrige måned</1>",
"newer_posts_available": "Nyere innlegg tilgjengelige, <1>oppdater feed</1>"
"newer_posts_available": "Nyere innlegg tilgjengelige, <1>oppdater feed</1>",
"stored_locally": "Lagring lokalt ({{location}}), ikke synkronisert på tvers av enheter",
"choose_one": "Velg en:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Nie można opublikować pustego komentarza.",
"more_posts_last_week": "Pokazuje posty od {{currentTimeFilterName}}, <1>pokaż więcej postów z zeszłego tygodnia</1>",
"more_posts_last_month": "Pokazuje posty od {{currentTimeFilterName}}, <1>pokaż więcej postów z zeszłego miesiąca</1>",
"newer_posts_available": "Dostępne są nowsze posty, <1>przeładuj kanał</1>"
"newer_posts_available": "Dostępne są nowsze posty, <1>przeładuj kanał</1>",
"stored_locally": "Przechowywane lokalnie ({{location}}), nie synchronizowane między urządzeniami",
"choose_one": "Wybierz jeden:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Não é possível postar um comentário vazio.",
"more_posts_last_week": "Exibindo postagens desde {{currentTimeFilterName}}, <1>mostrar mais postagens da semana passada</1>",
"more_posts_last_month": "Exibindo postagens desde {{currentTimeFilterName}}, <1>atualize o feed com mais postagens do mês passado</1>",
"newer_posts_available": "Novos posts disponíveis, <1>atualize o feed</1>"
"newer_posts_available": "Novos posts disponíveis, <1>atualize o feed</1>",
"stored_locally": "Armazenado localmente ({{location}}), não sincronizado entre dispositivos",
"choose_one": "Escolha um:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Nu se poate publica un comentariu gol.",
"more_posts_last_week": "Afișând postări din {{currentTimeFilterName}}, <1>afișați mai multe postări din săptămâna trecută</1>",
"more_posts_last_month": "Afișând postări din {{currentTimeFilterName}}, <1>afișați mai multe postări din luna trecută</1>",
"newer_posts_available": "Postări mai recente disponibile, <1>reîncarcă fluxul</1>"
"newer_posts_available": "Postări mai recente disponibile, <1>reîncarcă fluxul</1>",
"stored_locally": "Stocat local ({{location}}), nu este sincronizat între dispozitive",
"choose_one": "Alege una:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Невозможно опубликовать пустой комментарий.",
"more_posts_last_week": "Показаны записи с {{currentTimeFilterName}}, <1>показать больше записей за прошлую неделю</1>",
"more_posts_last_month": "Показаны записи с {{currentTimeFilterName}}, <1>показать больше записей за прошлый месяц</1>",
"newer_posts_available": "Доступны более новые записи, <1>обновите ленту</1>"
"newer_posts_available": "Доступны более новые записи, <1>обновите ленту</1>",
"stored_locally": "Сохранено локально ({{location}}), не синхронизировано между устройствами",
"choose_one": "Выберите один:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Nuk mund të postoni një koment bosh.",
"more_posts_last_week": "Duke treguar postimet që nga {{currentTimeFilterName}}, <1>tregoni më shumë postime nga java e kaluar</1>",
"more_posts_last_month": "Duke treguar postimet që nga {{currentTimeFilterName}}, <1>tregoni më shumë postime nga java e kaluar</1>",
"newer_posts_available": "Postime më të reja janë të disponueshme, <1>rifreskoje fluxin</1>"
"newer_posts_available": "Postime më të reja janë të disponueshme, <1>rifreskoje fluxin</1>",
"stored_locally": "Ruajtur lokalmente ({{location}}), nuk është sinkronizuar ndërmjet pajisjeve",
"choose_one": "Zgjidhni një:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Kan inte posta tom kommentar.",
"more_posts_last_week": "Visar inlägg sedan {{currentTimeFilterName}}, <1>visa fler inlägg från förra veckan</1>",
"more_posts_last_month": "Visar inlägg sedan {{currentTimeFilterName}}, <1>visa fler inlägg från förra månaden</1>",
"newer_posts_available": "Nyare inlägg tillgängliga, <1>ladda om flödet</1>"
"newer_posts_available": "Nyare inlägg tillgängliga, <1>ladda om flödet</1>",
"stored_locally": "Lagrad lokalt ({{location}}), inte synkroniserad mellan enheter",
"choose_one": "Välj en:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "ఖాళీ వ్యాఖ్యను పోస్ట్ చేయలేరు.",
"more_posts_last_week": "{{currentTimeFilterName}} నుండి పోస్టులు చూపిస్తున్నాయి, <1>గత వారంనుంచి మరిన్ని పోస్టులను చూపించు</1>",
"more_posts_last_month": "{{currentTimeFilterName}} నుండి పోస్టులు చూపిస్తున్నాయి, <1>గత నెల నుండి మరిన్ని పోస్టులను చూపించండి</1>",
"newer_posts_available": "కొత్త పోస్టులు అందుబాటులో ఉన్నాయి, <1>ఫీడ్‌ను తిరిగి లోడ్ చేయండి</1>"
"newer_posts_available": "కొత్త పోస్టులు అందుబాటులో ఉన్నాయి, <1>ఫీడ్‌ను తిరిగి లోడ్ చేయండి</1>",
"stored_locally": "స్థానికంగా నిల్వ ({{location}}), పరికరాల మధ్య సమన్వయించడం లేదు",
"choose_one": "ఒకటి ఎంపిక చేసుకోండి:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "ไม่สามารถโพสต์ความคิดเห็นว่างเปล่าได้",
"more_posts_last_week": "แสดงโพสต์ตั้งแต่ {{currentTimeFilterName}} <1>แสดงโพสต์เพิ่มเติมจากสัปดาห์ที่แล้ว</1>",
"more_posts_last_month": "โพสต์ตั้งแต่ {{currentTimeFilterName}} <1>แสดงโพสต์เพิ่มเติมจากเดือนที่แล้ว</1>",
"newer_posts_available": "โพสต์ใหม่พร้อมใช้งาน, <1>โหลดฟีดใหม่</1>"
"newer_posts_available": "โพสต์ใหม่พร้อมใช้งาน, <1>โหลดฟีดใหม่</1>",
"stored_locally": "จัดเก็บในเครื่อง ({{location}}) ไม่ได้ซิงค์ข้ามอุปกรณ์",
"choose_one": "เลือกหนึ่ง:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Boş yorum gönderilemez.",
"more_posts_last_week": "{{currentTimeFilterName}} tarihinden itibaren gönderiler gösteriliyor, <1>geçen haftadan daha fazla gönderi göster</1>",
"more_posts_last_month": "{{currentTimeFilterName}} tarihinden itibaren gönderiler gösteriliyor, <1>geçen aydan daha fazla gönderi göster</1>",
"newer_posts_available": "Daha yeni gönderiler mevcut, <1>beslemeyi yenile</1>"
"newer_posts_available": "Daha yeni gönderiler mevcut, <1>beslemeyi yenile</1>",
"stored_locally": "Yerel olarak saklanıyor ({{location}}), cihazlar arasında senkronize edilmedi",
"choose_one": "Birini seç:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Не можна опублікувати порожній коментар.",
"more_posts_last_week": "Показані пости з {{currentTimeFilterName}}, <1>показати більше постів з минулого тижня</1>",
"more_posts_last_month": "Показані пости з {{currentTimeFilterName}}, <1>показати більше постів з минулого місяця</1>",
"newer_posts_available": "Доступні нові пости, <1>перезавантажити стрічку</1>"
"newer_posts_available": "Доступні нові пости, <1>перезавантажити стрічку</1>",
"stored_locally": "Збережено локально ({{location}}), не синхронізується між пристроями",
"choose_one": "Виберіть один:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "خالی تبصرہ پوسٹ نہیں کیا جا سکتا۔",
"more_posts_last_week": "{{currentTimeFilterName}} سے پوسٹ دکھا رہا ہے، <1>پچھلے ہفتے کے مزید پوسٹس دکھائیں</1>",
"more_posts_last_month": "{{currentTimeFilterName}} سے پوسٹ دکھا رہا ہے، <1>پچھلے مہینے کے مزید پوسٹس دکھائیں</1>",
"newer_posts_available": "نئے پوسٹس دستیاب ہیں، <1>فیڈ کو دوبارہ لوڈ کریں</1>"
"newer_posts_available": "نئے پوسٹس دستیاب ہیں، <1>فیڈ کو دوبارہ لوڈ کریں</1>",
"stored_locally": "مقامی طور پر محفوظ ({{location}})، آلات کے درمیان ہم وقت سازی نہیں کی گئی",
"choose_one": "ایک کا انتخاب کریں:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "Không thể đăng bình luận trống.",
"more_posts_last_week": "Đang hiển thị bài viết từ {{currentTimeFilterName}}, <1>hiển thị thêm bài viết từ tuần trước</1>",
"more_posts_last_month": "Đang hiển thị bài viết từ {{currentTimeFilterName}}, <1>hiển thị thêm bài viết từ tháng trước</1>",
"newer_posts_available": "Có bài viết mới, <1>tải lại nguồn cấp dữ liệu</1>"
"newer_posts_available": "Có bài viết mới, <1>tải lại nguồn cấp dữ liệu</1>",
"stored_locally": "Lưu trữ cục bộ ({{location}}), không được đồng bộ qua các thiết bị",
"choose_one": "Chọn một:"
}
+3 -1
View File
@@ -239,5 +239,7 @@
"empty_comment_alert": "无法发布空评论。",
"more_posts_last_week": "显示自 {{currentTimeFilterName}} 以来的帖子,<1>显示上周的更多帖子</1>",
"more_posts_last_month": "显示自 {{currentTimeFilterName}} 以来的帖子,<1>显示上个月的更多帖子</1>",
"newer_posts_available": "新帖子可用,<1>重新加载源</1>"
"newer_posts_available": "新帖子可用,<1>重新加载源</1>",
"stored_locally": "本地存储 ({{location}}),未在设备之间同步",
"choose_one": "选择一个:"
}
+15 -7
View File
@@ -1,4 +1,4 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { Link, useLocation, useParams } from 'react-router-dom';
@@ -6,7 +6,8 @@ import { Comment, useComment } from '@plebbit/plebbit-react-hooks';
import { useFloating, offset, size, autoUpdate, Placement } from '@floating-ui/react';
import { fetchWebpageThumbnailIfNeeded, getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
import { getFormattedTimeAgo } from '../../lib/utils/time-utils';
import { isAllView } from '../../lib/utils/view-utils';
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import useCatalogStyleStore from '../../stores/use-catalog-style-store';
import useEditCommentPrivileges from '../../hooks/use-author-privileges';
import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
@@ -119,18 +120,24 @@ const CatalogPost = ({ post }: { post: Comment }) => {
const initialCommentMediaInfo = useMemo(() => getCommentMediaInfo(post), [post]);
const [commentMediaInfo, setCommentMediaInfo] = useState(initialCommentMediaInfo);
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
useEffect(() => {
const fetchThumbnail = useCallback(async () => {
if (initialCommentMediaInfo?.type === 'webpage' && !initialCommentMediaInfo.thumbnail) {
fetchWebpageThumbnailIfNeeded(initialCommentMediaInfo).then(setCommentMediaInfo);
} else {
setCommentMediaInfo(initialCommentMediaInfo);
const newMediaInfo = await fetchWebpageThumbnailIfNeeded(initialCommentMediaInfo);
setCommentMediaInfo(newMediaInfo);
}
}, [initialCommentMediaInfo]);
useEffect(() => {
fetchThumbnail();
}, [fetchThumbnail]);
const { hidden } = useHide({ cid });
const location = useLocation();
const isInAllView = isAllView(location.pathname, useParams());
const params = useParams();
const isInAllView = isAllView(location.pathname, params);
const isInSubscriptionsView = isSubscriptionsView(location.pathname, params);
const postLink = isInAllView && isDescription ? `/p/all/description` : `/p/${subplebbitAddress}/${isDescription ? 'description' : isRules ? 'rules' : `c/${cid}`}`;
@@ -288,6 +295,7 @@ const CatalogPost = ({ post }: { post: Comment }) => {
{author?.displayName || _.capitalize(t('anonymous'))}
{isCatalogPostAuthorMod && <span className='capitalize'>{` ## Board ${catalogPostAuthorRole}`}</span>}
</span>
{(isInAllView || isInSubscriptionsView) && subplebbitAddress && ` to p/${Plebbit.getShortAddress(subplebbitAddress)}`}
<span className={styles.postAgo}> {getFormattedTimeAgo(timestamp)}</span>
{replyCount > 0 && (
<div className={styles.postLast}>
+9 -5
View File
@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { Link, useLocation, useParams } from 'react-router-dom';
import { Comment, useAuthorAvatar, useComment, useEditedComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
@@ -212,14 +212,18 @@ const PostMedia = ({ post }: PostProps) => {
// some sites have CORS access, so the thumbnail can be fetched client-side, which is helpful if subplebbit.settings.fetchThumbnailUrls is false
const initialCommentMediaInfo = useMemo(() => getCommentMediaInfo(post), [post]);
const [commentMediaInfo, setCommentMediaInfo] = useState(initialCommentMediaInfo);
useEffect(() => {
const fetchThumbnail = useCallback(async () => {
if (initialCommentMediaInfo?.type === 'webpage' && !initialCommentMediaInfo.thumbnail) {
fetchWebpageThumbnailIfNeeded(initialCommentMediaInfo).then(setCommentMediaInfo);
} else {
setCommentMediaInfo(initialCommentMediaInfo);
const newMediaInfo = await fetchWebpageThumbnailIfNeeded(initialCommentMediaInfo);
setCommentMediaInfo(newMediaInfo);
}
}, [initialCommentMediaInfo]);
useEffect(() => {
fetchThumbnail();
}, [fetchThumbnail]);
const { url } = commentMediaInfo || {};
let type = commentMediaInfo?.type;
const gifFrameUrl = useFetchGifFirstFrame(url);
+19 -111
View File
@@ -1,111 +1,19 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import {
Comment,
PublishCommentOptions,
setAccount,
useAccount,
useAccountComment,
useComment,
useEditedComment,
usePublishComment,
useSubplebbit,
} from '@plebbit/plebbit-react-hooks';
import { create } from 'zustand';
import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils';
import { Comment, setAccount, useAccount, useAccountComment, useComment, useEditedComment, usePublishComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import { getHasThumbnail, getLinkMediaInfo } from '../../lib/utils/media-utils';
import { formatMarkdown } from '../../lib/utils/post-utils';
import { isValidURL } from '../../lib/utils/url-utils';
import { isAllView, isDescriptionView, isPostPageView, isRulesView, isSubscriptionsView } from '../../lib/utils/view-utils';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import usePublishReply from '../../hooks/use-publish-reply';
import useChallengesStore from '../../stores/use-challenges-store';
import styles from './post-form.module.css';
import _ from 'lodash';
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
import useFetchGifFirstFrame from '../../hooks/use-fetch-gif-first-frame';
import useAnonMode from '../../hooks/use-anon-mode';
type SubmitState = {
author?: any | undefined;
displayName?: string | undefined;
signer?: any | undefined;
subplebbitAddress: string | undefined;
title: string | undefined;
content: string | undefined;
link: string | undefined;
spoiler: boolean | undefined;
publishCommentOptions: PublishCommentOptions;
setSubmitStore: (data: Partial<SubmitState>) => void;
resetSubmitStore: () => void;
};
const { addChallenge } = useChallengesStore.getState();
const useSubmitStore = create<SubmitState>((set) => ({
author: undefined,
displayName: undefined,
signer: undefined,
subplebbitAddress: undefined,
title: undefined,
content: undefined,
link: undefined,
spoiler: undefined,
publishCommentOptions: {},
setSubmitStore: ({ author, displayName, signer, subplebbitAddress, title, content, link, spoiler }) =>
set((state) => {
const nextState = { ...state };
if (author !== undefined) nextState.author = author;
if (displayName !== undefined) nextState.displayName = displayName;
if (signer !== undefined) nextState.signer = signer;
if (subplebbitAddress !== undefined) nextState.subplebbitAddress = subplebbitAddress;
if (title !== undefined) nextState.title = title || undefined;
if (content !== undefined) nextState.content = content || undefined;
if (link !== undefined) nextState.link = link || undefined;
if (spoiler !== undefined) nextState.spoiler = spoiler || undefined;
const publishCommentOptions: PublishCommentOptions = {
subplebbitAddress: nextState.subplebbitAddress,
title: nextState.title,
content: nextState.content,
link: nextState.link,
spoiler: nextState.spoiler,
onChallenge: (...args: any) => addChallenge(args),
onChallengeVerification: alertChallengeVerificationFailed,
onError: (error: Error) => {
console.error(error);
alert(error.message);
},
};
if (nextState.signer) {
publishCommentOptions.signer = nextState.signer;
}
if (nextState.author || nextState.displayName) {
publishCommentOptions.author = {
...nextState.author,
displayName: nextState.displayName,
};
}
nextState.publishCommentOptions = publishCommentOptions;
return nextState;
}),
resetSubmitStore: () =>
set({
author: undefined,
displayName: undefined,
signer: undefined,
subplebbitAddress: undefined,
title: undefined,
content: undefined,
link: undefined,
spoiler: undefined,
publishCommentOptions: {},
}),
}));
import usePublishPostStore from '../../stores/use-publish-post-store';
export const LinkTypePreviewer = ({ link }: { link: string }) => {
const { t } = useTranslation();
@@ -128,14 +36,14 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
const author = account?.author || {};
const { displayName } = author || {};
const [url, setUrl] = useState('');
const { publishCommentOptions, setSubmitStore, resetSubmitStore } = useSubmitStore();
const { publishCommentOptions, setPublishPostStore, resetPublishPostStore } = usePublishPostStore();
const { index, publishComment } = usePublishComment(publishCommentOptions);
useEffect(() => {
if (displayName) {
setSubmitStore({ displayName });
setPublishPostStore({ displayName });
}
}, [displayName, setSubmitStore]);
}, [displayName, setPublishPostStore]);
const textRef = useRef<HTMLTextAreaElement>(null);
const urlRef = useRef<HTMLInputElement>(null);
@@ -170,7 +78,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
if (!hasCalledAnonAddressRef.current) {
hasCalledAnonAddressRef.current = true;
const newSigner = (await getNewSigner()) || {};
setSubmitStore({
setPublishPostStore({
signer: newSigner,
author: {
address: newSigner.address,
@@ -179,7 +87,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
});
}
} else {
setSubmitStore({
setPublishPostStore({
signer: undefined,
author: {
address: account?.author?.address,
@@ -187,7 +95,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
},
});
}
}, [anonMode, getNewSigner, account, setSubmitStore, displayName]);
}, [anonMode, getNewSigner, account, setPublishPostStore, displayName]);
const onPublishPost = () => {
const currentTitle = subjectRef.current?.value.trim() || '';
@@ -228,19 +136,19 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
const subplebbitAddress = params?.subplebbitAddress || accountComment?.subplebbitAddress;
useEffect(() => {
if (subplebbitAddress) {
setSubmitStore({ subplebbitAddress });
setPublishPostStore({ subplebbitAddress });
}
}, [subplebbitAddress, setSubmitStore]);
}, [subplebbitAddress, setPublishPostStore]);
// redirect to pending page when pending comment is created
const navigate = useNavigate();
useEffect(() => {
if (typeof index === 'number') {
resetSubmitStore();
resetPublishPostStore();
resetFields();
navigate(`/profile/${index}`);
}
}, [index, resetSubmitStore, navigate]);
}, [index, resetPublishPostStore, navigate]);
// in post page, publish a reply to the post
const isInPostView = isPostPageView(location.pathname, params);
@@ -274,7 +182,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
const handleContentChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const formattedContent = formatMarkdown(e.target.value);
isInPostView ? setPublishReplyOptions({ content: formattedContent }) : setSubmitStore({ content: formattedContent });
isInPostView ? setPublishReplyOptions({ content: formattedContent }) : setPublishPostStore({ content: formattedContent });
};
const onPublishReply = () => {
@@ -327,7 +235,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
if (isInPostView) {
setPublishReplyOptions({ displayName: e.target.value || undefined });
} else {
setSubmitStore({ displayName: e.target.value || undefined });
setPublishPostStore({ displayName: e.target.value || undefined });
}
}}
/>
@@ -342,7 +250,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
type='text'
ref={subjectRef}
onChange={(e) => {
setSubmitStore({ title: e.target.value || undefined });
setPublishPostStore({ title: e.target.value || undefined });
}}
/>
<button onClick={onPublishPost}>{t('post')}</button>
@@ -366,7 +274,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
ref={urlRef}
onChange={(e) => {
setUrl(e.target.value);
isInPostView ? setPublishReplyOptions({ link: e.target.value || undefined }) : setSubmitStore({ link: e.target.value || undefined });
isInPostView ? setPublishReplyOptions({ link: e.target.value || undefined }) : setPublishPostStore({ link: e.target.value || undefined });
}}
/>
<span className={styles.linkType}> {url && <LinkTypePreviewer link={url} />}</span>
@@ -379,7 +287,7 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
<label>
<input
type='checkbox'
onChange={(e) => (isInPostView ? setPublishReplyOptions({ spoiler: e.target.checked }) : setSubmitStore({ spoiler: e.target.checked }))}
onChange={(e) => (isInPostView ? setPublishReplyOptions({ spoiler: e.target.checked }) : setPublishPostStore({ spoiler: e.target.checked }))}
/>
{_.capitalize(t('spoiler'))}?
</label>
@@ -390,8 +298,8 @@ const PostFormTable = ({ closeForm, postCid }: { closeForm: () => void; postCid:
<tr>
<td>{t('board')}</td>
<td>
<select onChange={(e) => setSubmitStore({ subplebbitAddress: e.target.value })} value={subplebbitAddress}>
<option value=''>--{t('no_board_selected')}--</option>
<select onChange={(e) => setPublishPostStore({ subplebbitAddress: e.target.value })} value={subplebbitAddress}>
<option value=''>{t('choose_one')}</option>
{isInAllView &&
defaultSubplebbitAddresses.map((address: string) => (
<option key={address} value={address}>
+9 -5
View File
@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { Link, useLocation, useParams } from 'react-router-dom';
import { Comment, useAuthorAvatar, useComment, useEditedComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
@@ -43,14 +43,18 @@ const PostInfoAndMedia = ({ openReplyModal, post, postReplyCount = 0, roles }: P
// some sites have CORS access, so the thumbnail can be fetched client-side, which is helpful if subplebbit.settings.fetchThumbnailUrls is false
const initialCommentMediaInfo = useMemo(() => getCommentMediaInfo(post), [post]);
const [commentMediaInfo, setCommentMediaInfo] = useState(initialCommentMediaInfo);
useEffect(() => {
const fetchThumbnail = useCallback(async () => {
if (initialCommentMediaInfo?.type === 'webpage' && !initialCommentMediaInfo.thumbnail) {
fetchWebpageThumbnailIfNeeded(initialCommentMediaInfo).then(setCommentMediaInfo);
} else {
setCommentMediaInfo(initialCommentMediaInfo);
const newMediaInfo = await fetchWebpageThumbnailIfNeeded(initialCommentMediaInfo);
setCommentMediaInfo(newMediaInfo);
}
}, [initialCommentMediaInfo]);
useEffect(() => {
fetchThumbnail();
}, [fetchThumbnail]);
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
const [showThumbnail, setShowThumbnail] = useState(true);
@@ -47,6 +47,12 @@
margin-left: 5px;
}
.warning {
font-size: 0.8em;
color: red;
padding: 5px 0;
}
.settingTip {
display: block;
font-size: 0.85em;
@@ -4,6 +4,7 @@ import { createAccount, deleteAccount, exportAccount, importAccount, setAccount,
import stringify from 'json-stringify-pretty-compact';
import styles from './account-settings.module.css';
import useAnonModeStore from '../../../stores/use-anon-mode-store';
import { isAndroid } from '../../../lib/utils/platform';
const AnonMode = () => {
const { t } = useTranslation();
@@ -178,6 +179,12 @@ const AccountSettings = () => {
<button className={styles.createAccount} onClick={_createAccount}>
+
</button>
<div className={styles.warning}>
{t('stored_locally', {
location: window.isElectron ? 'this desktop app' : isAndroid ? 'this mobile app' : window.location.hostname,
interpolation: { escapeValue: false },
})}
</div>
</div>
<div></div>
<textarea value={text} onChange={(e) => setText(e.target.value)} autoCorrect='off' autoComplete='off' spellCheck='false' />
+1 -1
View File
@@ -51,7 +51,7 @@
position: fixed;
width: 100%;
z-index: 3;
transition: top 0.3s ease-in-out;
transition: top 0.2s ease-in-out;
align-items: center;
justify-content: space-around;
}
-1
View File
@@ -1,6 +1,5 @@
declare global {
interface Window {
STICKY_MENU_SCROLL_LISTENER: boolean;
isElectron: boolean;
}
}
+23 -1
View File
@@ -1,5 +1,18 @@
import { useEffect, useState } from 'react';
const GIF_FRAME_CACHE_KEY = 'gifFrameCache';
const getCachedGifFrame = (url: string): string | null => {
const cache = JSON.parse(localStorage.getItem(GIF_FRAME_CACHE_KEY) || '{}');
return cache[url] || null;
};
const setCachedGifFrame = (url: string, frameUrl: string): void => {
const cache = JSON.parse(localStorage.getItem(GIF_FRAME_CACHE_KEY) || '{}');
cache[url] = frameUrl;
localStorage.setItem(GIF_FRAME_CACHE_KEY, JSON.stringify(cache));
};
export const fetchImage = (url: string): Promise<ArrayBuffer> => {
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
@@ -62,9 +75,18 @@ const useFetchGifFirstFrame = (url: string | undefined) => {
const fetchFrame = async () => {
try {
const cachedFrame = getCachedGifFrame(url);
if (cachedFrame) {
if (isActive) setFrameUrl(cachedFrame);
return;
}
const blob = typeof url === 'string' ? await parseGif(await fetchImage(url)) : await parseGif(await readImage(url as File));
const objectUrl = URL.createObjectURL(blob);
if (isActive) setFrameUrl(objectUrl);
if (isActive) {
setFrameUrl(objectUrl);
setCachedGifFrame(url, objectUrl);
}
} catch (error) {
console.error('Failed to load GIF frame:', error);
if (isActive) setFrameUrl(null);
+7 -95
View File
@@ -1,102 +1,14 @@
import { useCallback } from 'react';
import { ChallengeVerification, Comment, PublishCommentOptions, useAccount, usePublishComment } from '@plebbit/plebbit-react-hooks';
import { create } from 'zustand';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
import useChallengesStore from '../stores/use-challenges-store';
import { useAccount, usePublishComment } from '@plebbit/plebbit-react-hooks';
import useAnonMode from './use-anon-mode';
import usePublishReplyStore, { SetReplyStoreData } from '../stores/use-publish-reply-store';
type SetReplyStoreData = {
subplebbitAddress: string;
parentCid: string;
author?: any;
displayName?: string;
content: string;
link?: string;
signer?: any;
spoiler: boolean;
};
type ReplyState = {
author: { [parentCid: string]: any | undefined };
displayName: { [parentCid: string]: string | undefined };
content: { [parentCid: string]: string | undefined };
link: { [parentCid: string]: string | undefined };
signer: { [parentCid: string]: any | undefined };
spoiler: { [parentCid: string]: boolean | undefined };
publishCommentOptions: { [parentCid: string]: PublishCommentOptions | undefined };
setReplyStore: (data: SetReplyStoreData) => void;
resetReplyStore: (parentCid: string) => void;
};
const { addChallenge } = useChallengesStore.getState();
const useReplyStore = create<ReplyState>((set) => ({
author: {},
displayName: {},
content: {},
link: {},
signer: {},
spoiler: {},
publishCommentOptions: {},
setReplyStore: (data: SetReplyStoreData) =>
set((state) => {
const { subplebbitAddress, parentCid, author, displayName, content, link, signer, spoiler } = data;
const updatedAuthor = displayName ? { ...author, displayName } : author;
const publishCommentOptions: PublishCommentOptions = {
subplebbitAddress,
parentCid,
content,
link,
spoiler,
onChallenge: (...args: any) => addChallenge(args),
onChallengeVerification: (challengeVerification: ChallengeVerification, comment: Comment) => {
alertChallengeVerificationFailed(challengeVerification, comment);
},
onError: (error: Error) => {
console.error(error);
alert(error.message);
},
};
if (updatedAuthor) {
publishCommentOptions.author = updatedAuthor;
}
if (signer) {
publishCommentOptions.signer = signer;
}
return {
author: { ...state.author, [parentCid]: updatedAuthor },
displayName: { ...state.displayName, [parentCid]: displayName },
content: { ...state.content, [parentCid]: content },
link: { ...state.link, [parentCid]: link },
signer: { ...state.signer, [parentCid]: signer },
spoiler: { ...state.spoiler, [parentCid]: spoiler },
publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: publishCommentOptions },
};
}),
resetReplyStore: (parentCid) =>
set((state) => ({
author: { ...state.author, [parentCid]: undefined },
displayName: { ...state.displayName, [parentCid]: undefined },
content: { ...state.content, [parentCid]: undefined },
link: { ...state.link, [parentCid]: undefined },
signer: { ...state.signer, [parentCid]: undefined },
spoiler: { ...state.spoiler, [parentCid]: undefined },
publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: undefined },
})),
}));
const useReply = ({ cid, subplebbitAddress }: { cid: string; subplebbitAddress: string }) => {
const usePublishReply = ({ cid, subplebbitAddress }: { cid: string; subplebbitAddress: string }) => {
const parentCid = cid;
const account = useAccount();
const { anonMode } = useAnonMode();
const { author, signer, content, link, spoiler, publishCommentOptions } = useReplyStore((state) => ({
const { author, signer, content, link, spoiler, publishCommentOptions } = usePublishReplyStore((state) => ({
author: state.author[parentCid] || (account?.author ? { displayName: account.author.displayName || undefined } : undefined),
displayName: state.displayName[parentCid] || account?.author?.displayName,
signer: state.signer[parentCid],
@@ -106,8 +18,8 @@ const useReply = ({ cid, subplebbitAddress }: { cid: string; subplebbitAddress:
publishCommentOptions: state.publishCommentOptions[parentCid],
}));
const setReplyStore = useReplyStore((state) => state.setReplyStore);
const resetReplyStore = useReplyStore((state) => state.resetReplyStore);
const setReplyStore = usePublishReplyStore((state) => state.setReplyStore);
const resetReplyStore = usePublishReplyStore((state) => state.resetReplyStore);
const setPublishReplyOptions = useCallback(
(options: Partial<SetReplyStoreData>) => {
@@ -151,4 +63,4 @@ const useReply = ({ cid, subplebbitAddress }: { cid: string; subplebbitAddress:
return { setPublishReplyOptions, resetPublishReplyOptions, replyIndex: index, publishReply: publishComment, setReplyStore };
};
export default useReply;
export default usePublishReply;
+27 -8
View File
@@ -135,14 +135,6 @@ const fetchWebpageThumbnail = async (url: string): Promise<string | undefined> =
}
};
export const fetchWebpageThumbnailIfNeeded = async (commentMediaInfo: CommentMediaInfo): Promise<CommentMediaInfo> => {
if (commentMediaInfo.type === 'webpage' && !commentMediaInfo.thumbnail) {
const thumbnail = await fetchWebpageThumbnail(commentMediaInfo.url);
return { ...commentMediaInfo, thumbnail };
}
return commentMediaInfo;
};
export const getCommentMediaInfo = (comment: Comment): CommentMediaInfo | undefined => {
if (!comment?.thumbnailUrl && !comment?.link) {
return;
@@ -192,3 +184,30 @@ export const getMediaDimensions = (commentMediaInfo: CommentMediaInfo | undefine
return '';
};
export const fetchWebpageThumbnailIfNeeded = async (commentMediaInfo: CommentMediaInfo): Promise<CommentMediaInfo> => {
if (commentMediaInfo.type === 'webpage' && !commentMediaInfo.thumbnail) {
const cachedThumbnail = getCachedThumbnail(commentMediaInfo.url);
if (cachedThumbnail) {
return { ...commentMediaInfo, thumbnail: cachedThumbnail };
}
const thumbnail = await fetchWebpageThumbnail(commentMediaInfo.url);
if (thumbnail) {
setCachedThumbnail(commentMediaInfo.url, thumbnail);
}
return { ...commentMediaInfo, thumbnail };
}
return commentMediaInfo;
};
const THUMBNAIL_CACHE_KEY = 'webpageThumbnailCache';
export const getCachedThumbnail = (url: string): string | null => {
const cache = JSON.parse(localStorage.getItem(THUMBNAIL_CACHE_KEY) || '{}');
return cache[url] || null;
};
export const setCachedThumbnail = (url: string, thumbnail: string): void => {
const cache = JSON.parse(localStorage.getItem(THUMBNAIL_CACHE_KEY) || '{}');
cache[url] = thumbnail;
localStorage.setItem(THUMBNAIL_CACHE_KEY, JSON.stringify(cache));
};
+8
View File
@@ -0,0 +1,8 @@
import { Capacitor } from '@capacitor/core';
import { Device } from '@capacitor/device';
export const isAndroid = Capacitor.getPlatform() === 'android';
export async function getDeviceInfo() {
return await Device.getInfo();
}
+86
View File
@@ -0,0 +1,86 @@
import { PublishCommentOptions } from '@plebbit/plebbit-react-hooks';
import { create } from 'zustand';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
import useChallengesStore from './use-challenges-store';
type SubmitState = {
author?: any | undefined;
displayName?: string | undefined;
signer?: any | undefined;
subplebbitAddress: string | undefined;
title: string | undefined;
content: string | undefined;
link: string | undefined;
spoiler: boolean | undefined;
publishCommentOptions: PublishCommentOptions;
setPublishPostStore: (data: Partial<SubmitState>) => void;
resetPublishPostStore: () => void;
};
const { addChallenge } = useChallengesStore.getState();
const usePublishPostStore = create<SubmitState>((set) => ({
author: undefined,
displayName: undefined,
signer: undefined,
subplebbitAddress: undefined,
title: undefined,
content: undefined,
link: undefined,
spoiler: undefined,
publishCommentOptions: {},
setPublishPostStore: ({ author, displayName, signer, subplebbitAddress, title, content, link, spoiler }) =>
set((state) => {
const nextState = { ...state };
if (author !== undefined) nextState.author = author;
if (displayName !== undefined) nextState.displayName = displayName;
if (signer !== undefined) nextState.signer = signer;
if (subplebbitAddress !== undefined) nextState.subplebbitAddress = subplebbitAddress;
if (title !== undefined) nextState.title = title || undefined;
if (content !== undefined) nextState.content = content || undefined;
if (link !== undefined) nextState.link = link || undefined;
if (spoiler !== undefined) nextState.spoiler = spoiler || undefined;
const publishCommentOptions: PublishCommentOptions = {
subplebbitAddress: nextState.subplebbitAddress,
title: nextState.title,
content: nextState.content,
link: nextState.link,
spoiler: nextState.spoiler,
onChallenge: (...args: any) => addChallenge(args),
onChallengeVerification: alertChallengeVerificationFailed,
onError: (error: Error) => {
console.error(error);
alert(error.message);
},
};
if (nextState.signer) {
publishCommentOptions.signer = nextState.signer;
}
if (nextState.author || nextState.displayName) {
publishCommentOptions.author = {
...nextState.author,
displayName: nextState.displayName,
};
}
nextState.publishCommentOptions = publishCommentOptions;
return nextState;
}),
resetPublishPostStore: () =>
set({
author: undefined,
displayName: undefined,
signer: undefined,
subplebbitAddress: undefined,
title: undefined,
content: undefined,
link: undefined,
spoiler: undefined,
publishCommentOptions: {},
}),
}));
export default usePublishPostStore;
+92
View File
@@ -0,0 +1,92 @@
import { ChallengeVerification, Comment, PublishCommentOptions } from '@plebbit/plebbit-react-hooks';
import { create } from 'zustand';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
import useChallengesStore from './use-challenges-store';
export type SetReplyStoreData = {
subplebbitAddress: string;
parentCid: string;
author?: any;
displayName?: string;
content: string;
link?: string;
signer?: any;
spoiler: boolean;
};
type ReplyState = {
author: { [parentCid: string]: any | undefined };
displayName: { [parentCid: string]: string | undefined };
content: { [parentCid: string]: string | undefined };
link: { [parentCid: string]: string | undefined };
signer: { [parentCid: string]: any | undefined };
spoiler: { [parentCid: string]: boolean | undefined };
publishCommentOptions: { [parentCid: string]: PublishCommentOptions | undefined };
setReplyStore: (data: SetReplyStoreData) => void;
resetReplyStore: (parentCid: string) => void;
};
const { addChallenge } = useChallengesStore.getState();
const usePublishReplyStore = create<ReplyState>((set) => ({
author: {},
displayName: {},
content: {},
link: {},
signer: {},
spoiler: {},
publishCommentOptions: {},
setReplyStore: (data: SetReplyStoreData) =>
set((state) => {
const { subplebbitAddress, parentCid, author, displayName, content, link, signer, spoiler } = data;
const updatedAuthor = displayName ? { ...author, displayName } : author;
const publishCommentOptions: PublishCommentOptions = {
subplebbitAddress,
parentCid,
content,
link,
spoiler,
onChallenge: (...args: any) => addChallenge(args),
onChallengeVerification: (challengeVerification: ChallengeVerification, comment: Comment) => {
alertChallengeVerificationFailed(challengeVerification, comment);
},
onError: (error: Error) => {
console.error(error);
alert(error.message);
},
};
if (updatedAuthor) {
publishCommentOptions.author = updatedAuthor;
}
if (signer) {
publishCommentOptions.signer = signer;
}
return {
author: { ...state.author, [parentCid]: updatedAuthor },
displayName: { ...state.displayName, [parentCid]: displayName },
content: { ...state.content, [parentCid]: content },
link: { ...state.link, [parentCid]: link },
signer: { ...state.signer, [parentCid]: signer },
spoiler: { ...state.spoiler, [parentCid]: spoiler },
publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: publishCommentOptions },
};
}),
resetReplyStore: (parentCid) =>
set((state) => ({
author: { ...state.author, [parentCid]: undefined },
displayName: { ...state.displayName, [parentCid]: undefined },
content: { ...state.content, [parentCid]: undefined },
link: { ...state.link, [parentCid]: undefined },
signer: { ...state.signer, [parentCid]: undefined },
spoiler: { ...state.spoiler, [parentCid]: undefined },
publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: undefined },
})),
}));
export default usePublishReplyStore;
+1
View File
@@ -1,4 +1,5 @@
.footer {
color: var(--post-mobile-abbr-text-color);
padding: 15px 0 10px 5px;
}
+1
View File
@@ -1,5 +1,6 @@
.footer {
padding: 15px 0 10px 5px;
color: var(--post-mobile-abbr-text-color);
}
.footer a {
+79 -52
View File
@@ -1199,45 +1199,51 @@
ipaddr.js "^2.1.0"
punycode "^2.3.1"
"@capacitor/android@3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@capacitor/android/-/android-3.6.0.tgz#60438a0614415c7c242dda48a031cd45335e067a"
integrity sha512-X6n0OLy7BE3c6qfVuL7UYyq/aIwEsqIAqtyDOwMdj5k+P1rLQVsGaWERXUtC0BGeoKBD5YgbWiyKwAwg5Spjdg==
"@capacitor/android@5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@capacitor/android/-/android-5.0.0.tgz#4e716738e87733b24c4a60e4c2e73fc4027fd2df"
integrity sha512-jEhx0OW8uypxlW94bXn7Q6YtwBOg3MH49DxH+jSrroRPr8Xb55w3puVSof9O2BQaxOq1mXKTjwz6TOIargGHwQ==
"@capacitor/app@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@capacitor/app/-/app-1.1.1.tgz#bde7202faad1b47c4ae2c4a622285d7569384c5e"
integrity sha512-8ADkldHnoE1xkWvPUsGlERVGm6/Zvcxy6hCI80AxydIKyaCG7kbDAvUclebbnw/eFRxj2zBoVatGLjmJNvTbYw==
"@capacitor/cli@3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@capacitor/cli/-/cli-3.6.0.tgz#31c07f364828e750d20a8e6bb2d516f0d21be81d"
integrity sha512-YNQNM1wvy3zJkKNWcNL5KzIqgV5J1YzO27MHSxZyVA6+XmWCZi8Qz/Cq/uDrepsuBG67QdIvtOeL+JnXARedfw==
"@capacitor/cli@5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@capacitor/cli/-/cli-5.0.0.tgz#baade00bb120ae2aa466ddf06adb3effb80cad06"
integrity sha512-d11L9xnnxmjyTHD3vjhOGnr7zN+uIzIeW4QrQC131rovP1cdFYVjG1DrmQa/mx6s49d2Bv7myNLHtl0j+dQIow==
dependencies:
"@ionic/cli-framework-output" "^2.2.1"
"@ionic/utils-fs" "^3.1.5"
"@ionic/utils-subprocess" "^2.1.6"
"@ionic/utils-terminal" "^2.3.0"
commander "^6.0.0"
debug "^4.2.0"
"@ionic/cli-framework-output" "^2.2.5"
"@ionic/utils-fs" "^3.1.6"
"@ionic/utils-subprocess" "^2.1.11"
"@ionic/utils-terminal" "^2.3.3"
commander "^9.3.0"
debug "^4.3.4"
env-paths "^2.2.0"
kleur "^4.1.1"
native-run "^1.5.0"
open "^7.4.2"
plist "^3.0.2"
prompts "^2.3.2"
semver "^7.3.2"
kleur "^4.1.4"
native-run "^1.7.2"
open "^8.4.0"
plist "^3.0.5"
prompts "^2.4.2"
rimraf "^4.4.1"
semver "^7.3.7"
tar "^6.1.11"
tslib "^2.1.0"
xml2js "^0.4.23"
tslib "^2.4.0"
xml2js "^0.5.0"
"@capacitor/core@3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@capacitor/core/-/core-3.6.0.tgz#5481a3c1c4d03cec77bb102fa5f7cbb0bd4c6f4d"
integrity sha512-F94ozABHXxq1xMcNGMnOVP73WZDWYR1PrJEfVfl9Ja0BXGEJURIxmHBc842OX3rrt3+g0ELHyhX9LTH16eeonw==
"@capacitor/core@5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@capacitor/core/-/core-5.0.0.tgz#31264d3708cb9c8de35024ad0be51c48adc560df"
integrity sha512-Fm8jNUPpCBPQVKLEwMt7D+w/7sh1AGiLVpL+D6Xc7iRdrPU/3NI9bgzca3uzDA1SOV8O+tVxk7bjZGXPbiTRAA==
dependencies:
tslib "^2.1.0"
"@capacitor/device@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@capacitor/device/-/device-6.0.1.tgz#bb5cb2b9e9c37142b71d51e4c6eed84625ce821e"
integrity sha512-Tlz67DAO5GKb5YAfupXiENZxDww6mHnG9iKI+8D5SVF82VLpEv5r9qwKtiounuQB2y2HWiHV8tlOk7DqnLVUqQ==
"@chainsafe/as-chacha20poly1305@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@chainsafe/as-chacha20poly1305/-/as-chacha20poly1305-0.1.0.tgz#7da6f8796f9b42dac6e830a086d964f1f9189e09"
@@ -2279,7 +2285,7 @@
resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-5.0.0.tgz#bf344cc75136039bc41bcf5d1ddbcb40405fca3b"
integrity sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==
"@ionic/cli-framework-output@^2.2.1":
"@ionic/cli-framework-output@^2.2.5":
version "2.2.8"
resolved "https://registry.yarnpkg.com/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz#29d541acc7773a6aaceec5f3b079937fbcef5402"
integrity sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==
@@ -2334,7 +2340,7 @@
debug "^4.0.0"
tslib "^2.0.1"
"@ionic/utils-subprocess@^2.1.6":
"@ionic/utils-subprocess@^2.1.11":
version "2.1.14"
resolved "https://registry.yarnpkg.com/@ionic/utils-subprocess/-/utils-subprocess-2.1.14.tgz#06224bdc6d9891ed86b1e556fc172a0eeabdc846"
integrity sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg==
@@ -2363,7 +2369,7 @@
untildify "^4.0.0"
wrap-ansi "^7.0.0"
"@ionic/utils-terminal@2.3.5", "@ionic/utils-terminal@^2.3.0", "@ionic/utils-terminal@^2.3.3":
"@ionic/utils-terminal@2.3.5", "@ionic/utils-terminal@^2.3.3":
version "2.3.5"
resolved "https://registry.yarnpkg.com/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz#a48465f40496ee8f29c6d92e4506d5f19762ac3c"
integrity sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==
@@ -6144,11 +6150,6 @@ commander@^5.0.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
commander@^6.0.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
commander@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
@@ -6159,6 +6160,11 @@ commander@^8.3.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
commander@^9.3.0:
version "9.5.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
commitizen@^4.0.3:
version "4.3.0"
resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-4.3.0.tgz#0d056c542a2d2b1f9b9aba981aa32575b2849924"
@@ -8932,6 +8938,16 @@ glob@^8.0.3:
minimatch "^5.0.1"
once "^1.3.0"
glob@^9.2.0:
version "9.3.5"
resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21"
integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==
dependencies:
fs.realpath "^1.0.0"
minimatch "^8.0.2"
minipass "^4.2.4"
path-scurry "^1.6.1"
global-agent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6"
@@ -10078,7 +10094,7 @@ is-windows@^1.0.1:
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
is-wsl@^2.1.1, is-wsl@^2.2.0:
is-wsl@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
@@ -11206,7 +11222,7 @@ kleur@^3.0.3:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
kleur@^4.0.3, kleur@^4.1.1:
kleur@^4.0.3, kleur@^4.1.4:
version "4.1.5"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780"
integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==
@@ -12293,6 +12309,13 @@ minimatch@^5.0.1, minimatch@^5.1.1:
dependencies:
brace-expansion "^2.0.1"
minimatch@^8.0.2:
version "8.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229"
integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==
dependencies:
brace-expansion "^2.0.1"
minimatch@^9.0.4:
version "9.0.5"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
@@ -12365,6 +12388,11 @@ minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
dependencies:
yallist "^4.0.0"
minipass@^4.2.4:
version "4.2.8"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a"
integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==
minipass@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
@@ -12537,7 +12565,7 @@ native-fetch@^4.0.2:
resolved "https://registry.yarnpkg.com/native-fetch/-/native-fetch-4.0.2.tgz#75c8a44c5f3bb021713e5e24f2846750883e49af"
integrity sha512-4QcVlKFtv2EYVS5MBgsGX5+NWKtbDbIECdUXDBGDMAZXq3Jkv9zf+y8iS7Ub8fEdga3GpYeazp9gauNqXHJOCg==
native-run@^1.5.0:
native-run@^1.7.2:
version "1.7.4"
resolved "https://registry.yarnpkg.com/native-run/-/native-run-1.7.4.tgz#b98b74812805cef8665cfceec651e66e662123e3"
integrity sha512-yDEwTp66vmXpqFiSQzz4sVQgyq5U58gGRovglY4GHh12ITyWa6mh6Lbpm2gViVOVD1JYFtYnwcgr7GTFBinXNA==
@@ -12915,14 +12943,6 @@ open-graph-scraper@6.3.3:
undici "^6.4.0"
validator "^13.11.0"
open@^7.4.2:
version "7.4.2"
resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321"
integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==
dependencies:
is-docker "^2.0.0"
is-wsl "^2.1.1"
open@^8.0.9, open@^8.4.0:
version "8.4.2"
resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
@@ -13229,7 +13249,7 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-scurry@^1.11.1:
path-scurry@^1.11.1, path-scurry@^1.6.1:
version "1.11.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
@@ -13353,7 +13373,7 @@ please-upgrade-node@^3.2.0:
dependencies:
semver-compare "^1.0.0"
plist@^3.0.2, plist@^3.0.4, plist@^3.0.5, plist@^3.0.6:
plist@^3.0.4, plist@^3.0.5, plist@^3.0.6:
version "3.1.0"
resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9"
integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==
@@ -14037,7 +14057,7 @@ promise@^8.1.0:
dependencies:
asap "~2.0.6"
prompts@^2.0.1, prompts@^2.3.2, prompts@^2.4.2:
prompts@^2.0.1, prompts@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
@@ -14829,6 +14849,13 @@ rimraf@^3.0.0, rimraf@^3.0.2:
dependencies:
glob "^7.1.3"
rimraf@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.4.1.tgz#bd33364f67021c5b79e93d7f4fa0568c7c21b755"
integrity sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==
dependencies:
glob "^9.2.0"
roarr@^2.15.3:
version "2.15.4"
resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd"
@@ -17504,10 +17531,10 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
xml2js@^0.4.23:
version "0.4.23"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==
xml2js@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7"
integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==
dependencies:
sax ">=0.6.0"
xmlbuilder "~11.0.0"