This commit is contained in:
世界 2020-04-18 22:13:39 +08:00
parent c4d6a75777
commit 2c1bbf8163
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
36 changed files with 488 additions and 358 deletions

View File

@ -23,8 +23,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'org.osmdroid:osmdroid-android:6.1.6'
implementation 'com.google.zxing:core:3.4.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.71"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5"
def okHttpVersion = '4.5.0'
@ -33,8 +32,8 @@ dependencies {
implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:$okHttpVersion"
implementation 'dnsjava:dnsjava:3.0.2'
implementation 'org.dizitart:nitrite:3.4.1'
implementation 'net.lingala.zip4j:zip4j:2.5.1'
implementation 'cn.hutool:hutool-core:5.3.0'
implementation 'net.lingala.zip4j:zip4j:2.5.2'
implementation 'cn.hutool:hutool-core:5.3.1'
implementation files('libs/libv2ray.aar')
implementation files('libs/ss-libev-release.aar')

View File

@ -193,7 +193,7 @@
<string name="FilterNoChatsToDisplayInfo">目前沒有聊天屬於此資料夾。</string>
<string name="MessageLifetimeChanged">%1$s 將閱後即焚計時器設定為 %2$s</string>
<string name="PassportLanguage_TR">土耳其文</string>
<string name="FollowersChartTitle">追隨</string>
<string name="FollowersChartTitle">訂閱</string>
<string name="PassportLanguage_SL">斯洛維尼亞文</string>
<string name="PassportLanguage_SK">斯洛伐克文</string>
<string name="SendMessagesToText">您是否要將此訊息傳送到**%1$s**</string>
@ -230,7 +230,7 @@
<string name="SupportStatus">支援</string>
<string name="NotificationsExceptions">例外</string>
<string name="Stickers_many"></string>
<string name="FilterAvailableTitle">資料夾</string>
<string name="FilterAvailableTitle">聊天資料夾</string>
<string name="MinutesBold_many"></string>
<string name="PassportLanguage_UK">烏克蘭文</string>
<string name="SetUrlInvalidShort">連結必須至少包含5個字元。</string>
@ -351,7 +351,7 @@
<string name="Support">支援</string>
<string name="VoipExchangingKeys">正在交換加密金鑰</string>
<string name="InstantView">即時瀏覽</string>
<string name="IVInteractionsChartTitle">IV 互動</string>
<string name="IVInteractionsChartTitle">即時瀏覽互動</string>
<string name="DeleteMega">刪除群組</string>
<string name="TextSelectionHit">按住**文字**,然後移動游標以選擇更多文字進行複製。</string>
<string name="AccDescrPageDown">跳轉到底部</string>
@ -524,7 +524,7 @@ Telegram 團隊</string>
<string name="Devices">裝置</string>
<string name="AreYouSureDeletePhotoTitle">刪除照片</string>
<string name="SettingsRecent">最近的搜尋</string>
<string name="NewFollowersBySourceChartTitle">追隨者來源</string>
<string name="NewFollowersBySourceChartTitle">訂閱者的來源</string>
<string name="PassportResidentialAddress">居住地址</string>
<string name="Months_other">%1$d 個月</string>
<string name="ForwardedSticker_one"></string>
@ -567,7 +567,7 @@ Telegram 團隊</string>
<string name="MegaLeaveAlert">您確定要退出群組?</string>
<string name="BytesReceived">已接收的位元組</string>
<string name="NotificationsLedInfo">LED 在某些裝置上是一個閃爍的小燈,用於指示新訊息。</string>
<string name="FilterRemoveExclusionUserText">您確定要從排除的列表中移除「%1$s」嗎</string>
<string name="FilterRemoveExclusionUserText">您確定要從排除的聊天中移除「%1$s」嗎</string>
<string name="P2PEnabledWith">與誰通話使用點對點傳輸?</string>
<string name="PassportCountry">國家</string>
<string name="SearchFriends">搜尋聯絡人</string>
@ -622,7 +622,7 @@ Telegram 團隊</string>
<string name="AddToExistingContact">加入到現有聯絡資訊</string>
<string name="NotificationMessageGroupInvoice">%1$s 傳了一張總計 %3$s 的請款單到「%2$s」群組</string>
<string name="Italic">斜體</string>
<string name="PinFolderLimitReached">抱歉,您無法再將更多聊天置頂。</string>
<string name="PinFolderLimitReached">抱歉,您無法再將更多聊天置頂。</string>
<string name="ForwardedMusic_other">%1$d 個轉傳的音訊檔</string>
<string name="EventLogStopPoll">un1 關閉了投票:</string>
<string name="NoMedia">在此聊天中分享照片和影片,並在您的任何裝置上存取。</string>
@ -674,7 +674,7 @@ Telegram 團隊</string>
<string name="Decline">拒絕</string>
<string name="RestorePasswordNoEmailTitle">抱歉</string>
<string name="SetRecoveryEmail">設定備援電子信箱</string>
<string name="DiceInfo">將🎲表情符號傳送到任何聊天,以從 Telegram 獲得一隨機數字。</string>
<string name="DiceInfo">將🎲表情符號傳送到任何聊天就可以從 Telegram 獲得一個隨機數字。</string>
<string name="PassportNoDocumentsInfo">您可以加入您的電話號碼、電子郵件地址、身分證明文件或住址。</string>
<string name="RepeatNotifications">重複通知</string>
<string name="SecretWebPageInfo">連結預覽將在 Telegram 伺服器上產生。我們不儲存有關您傳送的連結之資料。</string>
@ -917,7 +917,7 @@ Telegram 團隊</string>
<string name="Points_many"></string>
<string name="MembersCountSelected_other">%1$d / %2$d 已選取</string>
<string name="AllowReadCallLog">請允許 Telegram 讀取通話記錄,以便我們自動為您輸入驗證碼。</string>
<string name="PinToTopLimitReached">抱歉,您只能在主列表中置頂 %1$s。如果您想要更有組織在「封存的聊天」中允許無限置頂。</string>
<string name="PinToTopLimitReached">抱歉,您只能在主聊天列表中置頂 %1$s。如果您想要更有組織在「封存的聊天」中允許無限置頂。</string>
<string name="FilterRemoveChats">移除聊天</string>
<string name="June">六月</string>
<string name="BlockUserContactsTitle">聯絡人</string>
@ -1131,7 +1131,7 @@ Telegram 團隊</string>
<string name="UseProxySettings">使用 Proxy</string>
<string name="EventLogEditedChannelDescription"> un1 編輯了頻道簡介:</string>
<string name="NotificationsDefaultOff">預設(關閉)</string>
<string name="InAppSounds">應用內音效</string>
<string name="InAppSounds">程式內聲音</string>
<string name="ChooseFromSearch">搜尋網頁</string>
<string name="SdCard">記憶卡</string>
<string name="OneResult">1 項結果</string>
@ -1165,7 +1165,7 @@ Telegram 團隊</string>
<string name="SearchImagesInfo">網路搜尋</string>
<string name="AccActionPause">暫停</string>
<string name="MembersCountZero">最多 %1$s</string>
<string name="AttachInlineRestrictedForever">此群組的管理員已禁止您在這傳送內聯機器人的內容</string>
<string name="AttachInlineRestrictedForever">管理員已禁止您在此群組使用內聯機器人</string>
<string name="AreYouSureDeleteFewMessagesMega">您確定要為所有人刪除這些訊息嗎?</string>
<string name="UseProxyPort">連接埠</string>
<string name="ChatHintsDeleteAlert">您確定要從推薦中移除 **%1$s** 嗎?</string>
@ -1293,7 +1293,7 @@ Telegram 團隊</string>
<string name="DeleteForAll">也從所有人的裝置中刪除</string>
<string name="Message">新訊息</string>
<string name="AttachRound">視訊訊息</string>
<string name="AttachStickersRestrictedForever">此群組的管理員已禁止您在這傳送貼圖。</string>
<string name="AttachStickersRestrictedForever">管理員已禁止您在此群組傳送貼圖。</string>
<string name="NotificationHiddenChatName">Telegram</string>
<string name="EventLogFilterPinnedMessages">置頂訊息</string>
<string name="FilterRecommended">推薦的資料夾</string>
@ -1563,7 +1563,7 @@ Telegram 團隊</string>
<string name="SlowmodeOff">關閉</string>
<string name="PassportTranslation">翻譯</string>
<string name="ViewContact">查看聯絡資訊</string>
<string name="InAppVibrate">應用內震動</string>
<string name="InAppVibrate">程式內震動</string>
<string name="PaymentShippingAddress2Placeholder">地址 2街道</string>
<string name="ColorThemes">顏色主題</string>
<string name="ForwardedContact_many"></string>
@ -1628,7 +1628,7 @@ Telegram 團隊</string>
<string name="BlockUsersMessage">您想要封鎖 **%1$s**在 Telegram 上傳訊息和打電話給您嗎?</string>
<string name="AccDescrReplying">回覆</string>
<string name="NotificationsChannels">頻道</string>
<string name="FilterRemoveExclusionText">您確定要從排除的列表中移除「%1$s」嗎</string>
<string name="FilterRemoveExclusionText">您確定要從排除的聊天中移除「%1$s」嗎</string>
<string name="EnableProxyAlert">您確定要啟用此 Proxy</string>
<string name="YourPasswordSuccessText">您的兩步驟驗證密碼現在已經啟用了。</string>
<string name="ChangePasscode">變更密碼</string>
@ -1644,7 +1644,7 @@ Telegram 團隊</string>
<string name="PassportDeletePersonalAlert">您確定要刪除您的個人資料?</string>
<string name="PaymentShippingAddress">收件地址</string>
<string name="AccDescrStickerSet">貼圖包</string>
<string name="InAppPreview">應用內預覽</string>
<string name="InAppPreview">程式內預覽</string>
<string name="NotificationMessageGroupMusic">%1$s 傳了一個音訊檔到「%2$s」群組</string>
<string name="RecentlyViewedHide">隱藏</string>
<string name="BlockUserMultiTitle">封鎖用戶</string>
@ -1827,7 +1827,7 @@ Telegram 團隊</string>
<string name="DialogPin">置頂</string>
<string name="ShareYouLocationUnableManually">手動選擇</string>
<string name="GIFs_two"></string>
<string name="FilterRemoveExclusionChatText">您確定要從排除的列表中移除「%1$s」嗎</string>
<string name="FilterRemoveExclusionChatText">您確定要從排除的聊天中移除「%1$s」嗎</string>
<string name="ChatsSelectedClear_many"></string>
<string name="NotificationActionPinnedPhotoChannel">%1$s 置頂了一張照片</string>
<string name="RecordingAudio">正在錄製語音訊息…</string>
@ -1931,7 +1931,7 @@ Telegram 團隊</string>
<string name="AddMembersAlertTitle">新增 %1$s</string>
<string name="items_other">%1$d 項目</string>
<string name="Videos_few"></string>
<string name="GrowthChartTitle">成長</string>
<string name="GrowthChartTitle">訂閱人數的變化</string>
<string name="LiveLocationContext">即時位置</string>
<string name="AccDescrSearchByUser">依用戶篩選</string>
<string name="OnlineCount_many"></string>
@ -1953,9 +1953,9 @@ Telegram 團隊</string>
<string name="TapToChangePhone">點擊以變更電話號碼</string>
<string name="ChannelMessageQuiz2">%1$s 張貼了測驗「%2$s」</string>
<string name="Default">預設</string>
<string name="NoFilesInfo">資料夾是空的。</string>
<string name="NoFilesInfo">這個資料夾是空的。</string>
<string name="EventLogPromotedDeleteMessages">刪除訊息</string>
<string name="DebugMenuResetDialogs">重置聊天</string>
<string name="DebugMenuResetDialogs">重置所有聊天</string>
<string name="PassportAddTranslationPassportRegistrationInfo">上傳您護照註冊頁面的英文譯本掃描。</string>
<string name="ChannelPrivateInfo">私人頻道只能透過邀請連結加入。</string>
<string name="NewTheme">新的顏色主題</string>
@ -2035,7 +2035,7 @@ Telegram 團隊</string>
<string name="Months_zero"></string>
<string name="UserBioEmpty"></string>
<string name="ForwardedVideo_zero"></string>
<string name="PrivacyForwardsMessageLine">萊因哈特,我們需要找一些新的歌曲 🎶。</string>
<string name="PrivacyForwardsMessageLine">萊因哈特,我們需要找一些新的歌曲 🎶。</string>
<string name="Seconds_other">%1$d 秒鐘</string>
<string name="ChannelMessageSticker">%1$s 發布了一張貼圖</string>
<string name="VoipOffline">您目前處於離線狀態,請連線到網路以撥打電話。</string>
@ -2092,7 +2092,7 @@ Telegram 團隊</string>
<string name="PassportSelectBithdayDate">選擇出生日期</string>
<string name="EventLogPromotedChangeGroupInfo">變更群組資訊</string>
<string name="PassportNativeHeaderLang">您在%1$s中的名稱</string>
<string name="InAppNotifications">應用內通知</string>
<string name="InAppNotifications">程式內通知</string>
<string name="AddMembersAlertNamesText">您確定要將 %1$s 加入到 **%2$s**</string>
<string name="PaymentTransactionReview">交易確認</string>
<string name="ShowAsGrid">顯示為網格</string>
@ -2199,7 +2199,7 @@ Telegram 團隊</string>
<string name="PeopleNearbyEmpty">正在尋找您周圍的用戶…</string>
<string name="SendSticker">傳送貼圖</string>
<string name="AccDescrClosePlayer">關閉音樂播放器</string>
<string name="ChromeCustomTabs">應用內瀏覽器</string>
<string name="ChromeCustomTabs">程式內瀏覽器</string>
<string name="MessageScheduleSend">現在傳送</string>
<string name="Update">更新</string>
<string name="AccDescrIVTitle">標題</string>
@ -2233,7 +2233,7 @@ Telegram 團隊</string>
<string name="TelegramPassportDelete">刪除 Telegram Passport</string>
<string name="StickersBotInfo">歡迎畫家使用我們的 @Stickers 機器人來上傳他們所擁有的貼圖包。</string>
<string name="Times_zero"></string>
<string name="ConfirmDeleteCallLog">想要從通話記錄中刪除此項目嗎?</string>
<string name="ConfirmDeleteCallLog">確定要刪除這則通話記錄嗎?</string>
<string name="AutoDownloadVideos">影片</string>
<string name="ThemeInstallCount_many"></string>
<string name="ArchivedStickersEmpty">尚無封存的貼圖</string>
@ -2645,7 +2645,7 @@ Telegram 團隊</string>
<string name="ForwardedPoll_two"></string>
<string name="PleaseEnterCurrentPasswordTransfer">請輸入您的密碼以完成轉讓。</string>
<string name="AreYouSureDeleteVideoTitle">刪除影片</string>
<string name="CreateNewFilterInfo">為不同的聊天群建立資料夾,然後在它們之間快速切換。</string>
<string name="CreateNewFilterInfo">建立資料夾,將不同的聊天進行分類,然後就可以在它們之間輕鬆切換。</string>
<string name="GifsTab">動圖</string>
<string name="PassportMainPage">主頁面</string>
<string name="BadgeNumber">未讀數量標記</string>
@ -2659,9 +2659,9 @@ Telegram 團隊</string>
<string name="ThemePreviewDialogMessage3">🤷‍♂️ 貼圖</string>
<string name="ThemePreviewDialogMessage2">嘿,我已經更新了原始碼。</string>
<string name="OpenUrlAlert">開啟網址 %1$s</string>
<string name="ThemePreviewDialogMessage1">讓我想起中國人的證明</string>
<string name="ThemePreviewDialogMessage7">這些不是您正在尋找的機器人。</string>
<string name="ThemePreviewLine1">萊因哈特,我們需要找一些新的音樂 🎶。</string>
<string name="ThemePreviewDialogMessage1">讓我想起了一句中國諺語</string>
<string name="ThemePreviewDialogMessage7">這些不是您找的機器人。</string>
<string name="ThemePreviewLine1">萊因哈特,我們需要您找一些新的歌曲 🎶。</string>
<string name="ThemePreviewDialogMessage6">您好!</string>
<string name="ThemePreviewLine2">我現在甚至不能認真對待你。</string>
<string name="ThemePreviewDialogMessage5">Yohoho</string>
@ -2972,7 +2972,7 @@ Telegram 團隊</string>
<string name="QuizWrongAnswer">回答錯誤!</string>
<string name="LowDiskSpaceNeverRemove">永不刪除</string>
<string name="Groups_two"></string>
<string name="DebugMenuDisableCamera">停用應用內相機</string>
<string name="DebugMenuDisableCamera">停用程式內相機</string>
<string name="ThemeResetToDefaultsTitle">重置設定</string>
<string name="ForwardedPoll_few"></string>
<string name="MessageScheduledBotAction">訊息發布後,此操作將可用。</string>
@ -3049,7 +3049,7 @@ Telegram 團隊</string>
<string name="ThemePreviewDialog4">保羅紐曼</string>
<string name="ThemePreviewDialog1">伊娃夏</string>
<string name="AutoDownloadOnRoamingData">漫遊時</string>
<string name="ThemePreviewDialog2">你內心的比賽</string>
<string name="ThemePreviewDialog2">你內心的競爭</string>
<string name="PaymentTransactionTotal">總計</string>
<string name="NoRecentSearches">最近沒有搜尋</string>
<string name="Long"></string>
@ -3060,7 +3060,7 @@ Telegram 團隊</string>
<string name="SentAppCode">我們已經傳送驗證碼到您其它裝置上的 **Telegram** 應用程式。</string>
<string name="NotificationActionPinnedGameChannel">%1$s 置頂了一個遊戲</string>
<string name="ThemePreviewDialog7">尼克K.</string>
<string name="FilterRemoveInclusionUserText">您確定要從包含的列表中移除「%1$s」嗎</string>
<string name="FilterRemoveInclusionUserText">您確定要從包含的聊天中移除「%1$s」嗎</string>
<string name="ThemePreviewDialog8">阿德勒托伯</string>
<string name="SendingGif">正在傳送 GIF 動圖…</string>
<string name="BotHelp">幫助</string>
@ -3153,7 +3153,7 @@ Telegram 團隊</string>
<string name="CallsDataUsage">通話設定</string>
<string name="NotificationsForGroups">群組通知</string>
<string name="EventLogOriginalCaptionEmpty">空的</string>
<string name="PinToTopLimitReached2">抱歉,在主列表中,您只能將 %1$s置頂。但是在「資料夾」和「封存」中則可以將更多聊天置頂。</string>
<string name="PinToTopLimitReached2">抱歉,在主聊天列表中,您只能將 %1$s置頂。但是在「聊天資料夾」和「封存的聊天」中,則可以將更多聊天置頂。</string>
<string name="EventLogRestrictedPinMessages">置頂訊息</string>
<string name="NotificationActionPinnedPoll2">%1$s 在「%2$s」群組中置頂了一項投票活動「%3$s」</string>
<string name="UseProxySponsorInfo">此頻道是由您使用的 Proxy 所顯示。要從聊天列表中刪除此頻道,請在「設定」中停用該 Proxy。</string>
@ -3162,7 +3162,7 @@ Telegram 團隊</string>
<string name="AppName">Telegram</string>
<string name="ColorPickerBackground">背景</string>
<string name="CropImage">裁切圖片</string>
<string name="FilterRemoveInclusionChatText">您確定要從包含的列表中移除「%1$s」嗎</string>
<string name="FilterRemoveInclusionChatText">您確定要從包含的聊天中移除「%1$s」嗎</string>
<string name="NoBlockedChannel">封鎖名單上的用戶將從頻道中移除,只能透過管理員的邀請回來,邀請連結對他們無效。</string>
<string name="FavoriteStickers">最愛</string>
<string name="EventLogFilterLeavingMembers">成員退出</string>
@ -3175,7 +3175,7 @@ Telegram 團隊</string>
<string name="CreateNewThemeAlert">您可以透過變更程式內的顏色來建立自己的主題。
您也可以隨時切換回預設主題。</string>
<string name="DebugMenuEnableCamera">啟用應用內相機</string>
<string name="DebugMenuEnableCamera">啟用程式內相機</string>
<string name="VoipOutgoingCall">正在進行 Telegram 通話</string>
<string name="ActionChannelRemovedPhoto">頻道照片已移除</string>
<string name="TypeLocationGroup">連結</string>
@ -3341,7 +3341,7 @@ Telegram 團隊</string>
<string name="EventLogChangedLinkedChannel">un1 連結了本群組與 «un2» 頻道</string>
<string name="PassportPhoneInfo">輸入您的電話號碼</string>
<string name="Chats_zero"></string>
<string name="FilterRemoveInclusionText">您確定要從包含的列表中移除「%1$s」嗎</string>
<string name="FilterRemoveInclusionText">您確定要從包含的聊天中移除「%1$s」嗎</string>
<string name="FilterShowMoreChats_other">顯示另外 %1$d 個聊天</string>
<string name="AreYouSureDeleteSingleMessage">您確定要刪除這則訊息嗎?</string>
<string name="Voice_zero"></string>
@ -3556,7 +3556,7 @@ Telegram 團隊</string>
<string name="Account">帳號</string>
<string name="Times_two"></string>
<string name="FilterNameNonMuted">未關通知的</string>
<string name="TopHoursChartTitle">不同時段瀏覽次數的累計 (UTC)</string>
<string name="TopHoursChartTitle">每小時瀏覽次數 (UTC)</string>
<string name="AutoDownloadOnUpToFor">最大 %1$s%2$s</string>
<string name="AttachPhoto">照片</string>
<string name="NotificationsForChats">聊天通知</string>

View File

@ -2350,7 +2350,7 @@ Telegramのアカウントを元に戻す事はできません。
<string name="Days_few"></string>
<string name="Emoji">絵文字</string>
<string name="ColorGreen">緑色</string>
<string name="AddContactChat">連絡先登録</string>
<string name="AddContactChat">連絡先登録</string>
<string name="AutoNightScheduled">管理して使用する</string>
<string name="InviteTextNum_zero"></string>
<string name="PhoneNumberSearch">電話番号</string>
@ -2792,7 +2792,7 @@ Telegram Desktopをダウンロード。</string>
メニューボタンを押すと項目が表示されます。</string>
<string name="SendingSms">SMSを送信中</string>
<string name="CustomThemes">追加テーマ</string>
<string name="BlockContact">相手をブロックする</string>
<string name="BlockContact">ブロックする</string>
<string name="TurnPasswordOffQuestionTitle">パスワードを無効にする</string>
<string name="TelegramFAQ">Telegram FAQ</string>
<string name="ChannelEditPermissions">制限を設定する</string>
@ -2828,7 +2828,7 @@ Telegram Desktopをダウンロード。</string>
<string name="AccDescrMusicInfo">%2$s %1$s</string>
<string name="ShareMyPhone">電話番号を共有する</string>
<string name="NotificationActionPinnedContact">%1$sが%2$sで連絡先を留めました</string>
<string name="EditAdminRank">肩書き</string>
<string name="EditAdminRank">呼び名</string>
<string name="ForwardedRound_few"></string>
<string name="NearbyPlaces">場所を指定する事も可能です</string>
<string name="NoSharedVoice">共有した音声は
@ -3483,7 +3483,7 @@ Telegramに通話を許可してください。</string>
<string name="PassportPhoneInfo">電話番号を入力してください</string>
<string name="Chats_zero"></string>
<string name="FilterRemoveInclusionText">「%1$s」を項目から削除しますか</string>
<string name="FilterShowMoreChats_other">%1$d をさらに表示</string>
<string name="FilterShowMoreChats_other">さらに%1$d個を表示</string>
<string name="AreYouSureDeleteSingleMessage">このメッセージを削除しますか?</string>
<string name="Voice_zero"></string>
<string name="PrivacyPhoneTitle">誰と電話番号でつながりますか?</string>

View File

@ -1,21 +1,14 @@
package com.v2ray.ang.util
import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.text.TextUtils
import android.util.Base64
import android.util.Patterns
import android.webkit.URLUtil
import com.google.zxing.WriterException
import org.json.JSONObject
import org.telegram.messenger.ApplicationLoader
import java.io.IOException
import java.net.Socket
import java.net.URLDecoder
import java.net.URLEncoder
import java.net.UnknownHostException
import java.util.*
object Utils {
@ -38,16 +31,32 @@ object Utils {
* base64 decode
*/
fun decode(text: String): String {
runCatching {
return Base64.decode(text, Base64.NO_PADDING or Base64.URL_SAFE or Base64.NO_WRAP).toString(charset("UTF-8"))
return runCatching {
Base64.decode(text, Base64.URL_SAFE or Base64.NO_WRAP).toString(charset("UTF-8"))
}.recoverCatching {
return Base64.decode(text, Base64.NO_PADDING).toString(charset("UTF-8"))
Base64.decode(text, Base64.NO_WRAP).toString(charset("UTF-8"))
}.recoverCatching {
return Base64.decode(text, Base64.NO_WRAP).toString(charset("UTF-8"))
}
return ""
Base64.decode(text, Base64.DEFAULT).toString(charset("UTF-8"))
}.getOrThrow()
}
fun decodeJson(text: String): String {
return runCatching {
Base64.decode(text, Base64.URL_SAFE or Base64.NO_WRAP).toString(charset("UTF-8")).also {
JSONObject(it)
}
}.recoverCatching {
Base64.decode(text, Base64.NO_WRAP).toString(charset("UTF-8")).also {
JSONObject(it)
}
}.recoverCatching {
Base64.decode(text, Base64.DEFAULT).toString(charset("UTF-8")).also {
JSONObject(it)
}
}.getOrThrow()
}
/**
* base64 encode
*/

View File

@ -1286,7 +1286,7 @@ public class AndroidUtilities {
String state = null;
try {
state = Environment.getExternalStorageState();
} catch (Exception e) {
} catch (Throwable e) {
FileLog.e(e);
}
if (state == null || state.startsWith(Environment.MEDIA_MOUNTED)) {
@ -1296,11 +1296,11 @@ public class AndroidUtilities {
FileUtil.initDir(file);
return file;
}
} catch (Exception e) {
} catch (Throwable e) {
FileLog.e(e);
}
}
return new File("");
return new File(ApplicationLoader.getDataDirFixed(),"cache/media");
}
public static int dp(float value) {

View File

@ -204,7 +204,7 @@ public class ApplicationLoader extends Application {
applicationHandler = new Handler(applicationContext.getMainLooper());
AndroidUtilities.runOnUIThread(ApplicationLoader::startPushService);
startPushService();
}

View File

@ -146,7 +146,7 @@ public class FileLog {
public static void e(final String message) {
Log.e(tag, message);
ExternalGcm.recordException(new Exception(message));
ExternalGcm.reportLog("[E]" + message);
if (!BuildVars.SAVE_LOG) return;
ensureInitied();
if (getInstance().streamWriter != null) {
@ -163,7 +163,7 @@ public class FileLog {
public static void e(final Throwable e) {
Log.e(tag,"ERR", e);
ExternalGcm.recordException(new Exception(e));
ExternalGcm.recordException(e);
if (!BuildVars.SAVE_LOG) return;
ensureInitied();
e.printStackTrace();
@ -187,6 +187,7 @@ public class FileLog {
public static void d(final String message) {
Log.d(tag, message);
ExternalGcm.reportLog("[D]" + message);
if (!BuildVars.SAVE_LOG) return;
ensureInitied();
if (getInstance().streamWriter != null) {

View File

@ -56,6 +56,7 @@ public class LocaleController {
static final int QUANTITY_MANY = 0x0010;
public static boolean isRTL = false;
public static int nameDisplayOrder = 1;
public static boolean is24HourFormat = false;
public FastDateFormat formatterDay;
@ -174,7 +175,7 @@ public class LocaleController {
File baseDir = new File(ApplicationLoader.getDataDirFixed(), "languages");
FileUtil.initDir(baseDir);
return new File(baseDir, "unofficial_base_" + shortName + ".xml");
return new File(baseDir, "remote_" + baseLangCode + ".xml");
}
return null;
}
@ -355,18 +356,6 @@ public class LocaleController {
languagesDict.put("zh_cn", localeInfo);
languagesDict.put("zh_sg", localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "祈翠";
localeInfo.nameEnglish = "Cuified Chinese (zh-zhao)";
localeInfo.shortName = "qicui";
localeInfo.baseLangCode = "zh_hans";
localeInfo.isRtl = false;
localeInfo.pathToFile = "unofficial";
localeInfo.pluralLangCode = "zh_cn";
localeInfo.builtIn = true;
languages.add(localeInfo);
languagesDict.put(localeInfo.getKey(), localeInfo);
localeInfo = new LocaleInfo();
localeInfo.name = "瓜体中文 \uD83D\uDE36";
localeInfo.nameEnglish = "Duangified Chinese (Simplified)";
@ -1827,6 +1816,7 @@ public class LocaleController {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("save locale file to " + finalFile);
}
FileUtil.initFile(finalFile);
BufferedWriter writer = new BufferedWriter(new FileWriter(finalFile));
writer.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
writer.write("<resources>\n");

View File

@ -147,11 +147,11 @@ public class MediaDataController extends BaseController {
private ArrayList<TLRPC.Document>[] recentStickers = new ArrayList[]{new ArrayList<>(), new ArrayList<>(), new ArrayList<>()};
private boolean[] loadingRecentStickers = new boolean[3];
public boolean[] recentStickersLoaded = new boolean[3];
private boolean[] recentStickersLoaded = new boolean[3];
private ArrayList<TLRPC.Document> recentGifs = new ArrayList<>();
private boolean loadingRecentGifs;
public boolean recentGifsLoaded;
private boolean recentGifsLoaded;
private int loadFeaturedHash;
private int loadFeaturedDate;

View File

@ -89,7 +89,7 @@ public class SharedConfig {
public static int passportConfigHash;
private static boolean configLoaded;
private static final Object sync = new Object();
public static final Object sync = new Object();
private static final Object localIdSync = new Object();
public static boolean saveToGallery;
@ -475,22 +475,13 @@ public class SharedConfig {
stop();
port = ProxyManager.getPortForBean(bean);
VmessLoader loader = new VmessLoader();
try {
loader.initConfig(bean);
VmessLoader loader = new VmessLoader();
loader.initConfig(bean, port);
port = loader.start();
loader.start();
this.loader = loader;
} catch (Exception e) {
FileLog.e(e);
}
this.loader = loader;
}
@ -765,6 +756,16 @@ public class SharedConfig {
public static LinkedList<ProxyInfo> proxyList = new LinkedList<>();
public static LinkedList<ProxyInfo> getProxyList() {
synchronized (sync) {
return new LinkedList<>(proxyList);
}
}
private static boolean proxyListLoaded;
public static ProxyInfo currentProxy;
@ -1440,91 +1441,94 @@ public class SharedConfig {
int current = MessagesController.getGlobalMainSettings().getInt("current_proxy", 0);
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("nekoconfig", Activity.MODE_PRIVATE);
boolean hidePublicProxy = preferences.getBoolean("hide_public_proxy",true);
boolean hidePublicProxy = preferences.getBoolean("hide_public_proxy", true);
try {
if (!hidePublicProxy) {
VmessProxy publicProxy = new VmessProxy(VmessLoader.getPublic());
publicProxy.isPublic = true;
proxyList.add(publicProxy);
if (publicProxy.hashCode() == current) {
currentProxy = publicProxy;
publicProxy.start();
}
}
} catch (Exception e) {
FileLog.e(e);
}
File remoteProxyListFile = ProxyUtil.cacheFile;
if (remoteProxyListFile.isFile() && !hidePublicProxy) {
synchronized (sync) {
try {
JSONArray proxyArray = new JSONArray(FileUtil.readUtf8String(remoteProxyListFile));
if (!hidePublicProxy) {
for (int a = 0; a < proxyArray.length(); a++) {
VmessProxy publicProxy = new VmessProxy(VmessLoader.getPublic());
publicProxy.isPublic = true;
proxyList.add(publicProxy);
JSONObject proxyObj = proxyArray.getJSONObject(a);
if (publicProxy.hashCode() == current) {
ProxyInfo info;
currentProxy = publicProxy;
try {
if (!proxyObj.isNull("proxy")) {
// old remote protocol
info = parseProxyInfo(proxyObj.getString("proxy"));
} else {
info = ProxyInfo.fromJson(proxyObj);
}
} catch (Exception ex) {
FileLog.e("load proxy failed", ex);
continue;
}
info.isPublic = true;
proxyList.add(info);
if (info.hashCode() == current) {
currentProxy = info;
if (info instanceof ExternalSocks5Proxy) {
((ExternalSocks5Proxy) info).start();
}
publicProxy.start();
}
}
} catch (Exception ex) {
} catch (Exception e) {
FileLog.e(e);
}
FileLog.e("invalid proxy list json format", ex);
File remoteProxyListFile = ProxyUtil.cacheFile;
if (remoteProxyListFile.isFile() && !hidePublicProxy) {
try {
JSONArray proxyArray = new JSONArray(FileUtil.readUtf8String(remoteProxyListFile));
for (int a = 0; a < proxyArray.length(); a++) {
JSONObject proxyObj = proxyArray.getJSONObject(a);
ProxyInfo info;
try {
if (!proxyObj.isNull("proxy")) {
// old remote protocol
info = parseProxyInfo(proxyObj.getString("proxy"));
} else {
info = ProxyInfo.fromJson(proxyObj);
}
} catch (Exception ex) {
FileLog.e("load proxy failed", ex);
continue;
}
info.isPublic = true;
proxyList.add(info);
if (info.hashCode() == current) {
currentProxy = info;
if (info instanceof ExternalSocks5Proxy) {
((ExternalSocks5Proxy) info).start();
}
}
}
} catch (Exception ex) {
FileLog.e("invalid proxy list json format", ex);
}
}
@ -1534,55 +1538,59 @@ public class SharedConfig {
boolean error = false;
if (proxyListFile.isFile()) {
synchronized (sync) {
try {
if (proxyListFile.isFile()) {
JSONArray proxyArray = new JSONArray(FileUtil.readUtf8String(proxyListFile));
try {
for (int a = 0; a < proxyArray.length(); a++) {
JSONArray proxyArray = new JSONArray(FileUtil.readUtf8String(proxyListFile));
JSONObject proxyObj = proxyArray.getJSONObject(a);
for (int a = 0; a < proxyArray.length(); a++) {
ProxyInfo info;
JSONObject proxyObj = proxyArray.getJSONObject(a);
try {
ProxyInfo info;
info = ProxyInfo.fromJson(proxyObj);
try {
} catch (Exception ex) {
info = ProxyInfo.fromJson(proxyObj);
FileLog.d("load proxy failed: " + ex);
} catch (Exception ex) {
error = true;
FileLog.d("load proxy failed: " + ex);
continue;
error = true;
}
continue;
if (!proxyObj.isNull("internal")) continue;
if (info.getTitle().toLowerCase().contains("nekox.me")) continue;
}
proxyList.add(info);
if (!proxyObj.isNull("internal")) continue;
if (info.getTitle().toLowerCase().contains("nekox.me")) continue;
if (info.hashCode() == current) {
proxyList.add(info);
currentProxy = info;
if (info.hashCode() == current) {
if (info instanceof ExternalSocks5Proxy) {
currentProxy = info;
((ExternalSocks5Proxy) info).start();
if (info instanceof ExternalSocks5Proxy) {
((ExternalSocks5Proxy) info).start();
}
}
}
} catch (Exception ex) {
FileLog.d("invalid proxy list json format" + ex);
}
} catch (Exception ex) {
FileLog.d("invalid proxy list json format" + ex);
}
}

View File

@ -4126,14 +4126,17 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
if (cancel.get()) return;
boolean finaL = taskCount.decrementAndGet() == 0;
if (errorCount.incrementAndGet() > 3 || finaL) {
UIUtil.runOnUIThread(dialog::dismiss);
adapter[0].trans = false;
transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate);
AlertUtil.showSimpleAlert(parentActivity, e.getMessage());
cancel.set(true);
transPool.shutdown();
AlertUtil.showTransFailedDialog(parentActivity, e instanceof UnsupportedOperationException, e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage(), this::doTransLATE);
UIUtil.runOnUIThread(() -> {
dialog.dismiss();
adapter[0].trans = false;
transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate);
});
}
AlertUtil.showSimpleAlert(parentActivity, e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage());
cancel.set(true);
transPool.shutdown();
AlertUtil.showTransFailedDialog(parentActivity, e instanceof UnsupportedOperationException, e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage(), this::doTransLATE);
return;
}

View File

@ -11,21 +11,26 @@ package org.telegram.ui;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Environment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLiteDatabase;
import org.telegram.SQLite.SQLitePreparedStatement;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLoader;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.R;
@ -49,8 +54,7 @@ import org.telegram.ui.Components.RecyclerListView;
import java.io.File;
import java.util.ArrayList;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import tw.nekomimi.nekogram.utils.FileUtil;
public class CacheControlActivity extends BaseFragment {
@ -98,6 +102,10 @@ public class CacheControlActivity extends BaseFragment {
Utilities.globalQueue.postRunnable(() -> {
cacheSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), 0);
cacheSize += getDirectorySize(new File(ApplicationLoader.getDataDirFixed(),"cache"),0);
cacheSize += getDirectorySize(ApplicationLoader.applicationContext.getExternalFilesDir("logs"),0);
if (canceled) {
return;
}
@ -197,6 +205,30 @@ public class CacheControlActivity extends BaseFragment {
if (type == FileLoader.MEDIA_DIR_CACHE) {
cacheSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), documentsMusicType);
imagesCleared = true;
try {
FileUtil.delete(new File(ApplicationLoader.getDataDirFixed(), "cache"));
} catch (Exception ignored) {
}
try {
FileUtil.delete(ApplicationLoader.applicationContext.getExternalFilesDir("logs"));
} catch (Exception ignored) {
}
try {
// :)
FileUtil.delete(Environment.getExternalStoragePublicDirectory("Telegram"));
} catch (Exception ignored) {
}
} else if (type == FileLoader.MEDIA_DIR_AUDIO) {
audioSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_AUDIO), documentsMusicType);
} else if (type == FileLoader.MEDIA_DIR_DOCUMENT) {
@ -215,6 +247,7 @@ public class CacheControlActivity extends BaseFragment {
stickersSize = getDirectorySize(new File(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), "acache"), documentsMusicType);
}
}
final boolean imagesClearedFinal = imagesCleared;
totalSize = cacheSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersSize;
AndroidUtilities.runOnUIThread(() -> {

View File

@ -16,6 +16,7 @@ import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -45,7 +46,6 @@ public class HeaderCell extends LinearLayout {
super(context);
setOrientation(LinearLayout.VERTICAL);
setPadding(AndroidUtilities.dp(padding), AndroidUtilities.dp(topMargin), AndroidUtilities.dp(padding), 0);
textView = new TextView(getContext());
@ -61,13 +61,18 @@ public class HeaderCell extends LinearLayout {
textView2 = new TextView(getContext());
textView2.setTextSize(13);
textView2.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
textView2.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP);
addView(textView2, LayoutHelper.createLinear(-2, -2, 0, 10, 0, 0));
addView(textView2, LayoutHelper.createLinear(-2, -2, 0, 4, 0, 0));
if (!text2) textView2.setVisibility(View.GONE);
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
params.width = -1;
super.setLayoutParams(params);
}
public void setHeight(int value) {
textView.setMinHeight(AndroidUtilities.dp(height = value) - ((LayoutParams) textView.getLayoutParams()).topMargin);
}

View File

@ -8782,6 +8782,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return 5;
} else if ((messageObject.getDocumentName().toLowerCase().endsWith(".nekox.json"))) {
return 21;
} else if ((messageObject.getDocumentName().toLowerCase().endsWith(".nekox-stickers.json"))) {
return 22;
} else if (!messageObject.isNewGif() && mime.endsWith("/mp4") || mime.endsWith("/png") || mime.endsWith("/jpg") || mime.endsWith("/jpeg")) {
return 6;
}
@ -14122,10 +14124,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
items.add(LocaleController.getString("ShareFile", R.string.ShareFile));
options.add(6);
icons.add(R.drawable.baseline_share_24);
} else if (type == 21) {
items.add(LocaleController.getString("ImportProxyList", R.string.ImportProxyList));
} else if (type == 21 || type == 22) {
options.add(5);
icons.add(R.drawable.baseline_security_24);
if (type == 21) {
items.add(LocaleController.getString("ImportProxyList", R.string.ImportProxyList));
icons.add(R.drawable.baseline_security_24);
} else {
items.add(LocaleController.getString("ImportStickersList", R.string.ImportStickersList));
icons.add(R.drawable.deproko_baseline_stickers_filled_24);
}
items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads));
options.add(10);
icons.add(R.drawable.baseline_file_download_24);
@ -14970,19 +14977,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
showDialog(builder.create());
}
} else if (locFile.getName().toLowerCase().endsWith(".json")) {
} else if (locFile.getName().toLowerCase().endsWith(".nekox.json")) {
File finalLocFile = locFile;
File finalLocFile1 = locFile;
AlertUtil.showConfirm(getParentActivity(),
LocaleController.getString("ImportProxyList", R.string.ImportProxyList),
LocaleController.getString("ImportProxyList", R.string.ImportProxyListConfirm),
LocaleController.getString("ImportProxyListConfirm", R.string.ImportProxyListConfirm),
LocaleController.getString("OK", R.string.OK), false, (d, v) -> {
String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile);
String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile1);
if (!StrUtil.isBlank(status)) {
presentFragment(new ProxyListActivity(status));
}
});
} else if (locFile.getName().toLowerCase().endsWith(".nekox-stickers.json")) {
File finalLocFile = locFile;
AlertUtil.showConfirm(getParentActivity(),
LocaleController.getString("ImportStickersList", R.string.ImportStickersList),
LocaleController.getString("ImportStickersConfirm", R.string.ImportStickersConfirm),
LocaleController.getString("OK", R.string.OK), false, (d, v) -> {
presentFragment(new StickersActivity(finalLocFile));
});
}
}
break;
@ -16827,7 +16844,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
File finalLocFile = locFile;
AlertUtil.showConfirm(getParentActivity(),
LocaleController.getString("ImportProxyList", R.string.ImportProxyList),
LocaleController.getString("ImportProxyList", R.string.ImportProxyListConfirm),
LocaleController.getString("ImportProxyListConfirm", R.string.ImportProxyListConfirm),
LocaleController.getString("OK", R.string.OK), false, (d, v) -> {
String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile);
if (!StrUtil.isBlank(status)) {
@ -16835,6 +16852,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
});
} else if (message.getDocumentName().toLowerCase().endsWith(".nekox-stickers.json")) {
File finalLocFile = locFile;
AlertUtil.showConfirm(getParentActivity(),
LocaleController.getString("ImportStickersList", R.string.ImportStickersList),
LocaleController.getString("ImportStickersConfirm", R.string.ImportStickersConfirm),
LocaleController.getString("OK", R.string.OK), false, (d, v) -> {
presentFragment(new StickersActivity(finalLocFile));
});
} else {
boolean handled = false;
if (message.canPreviewDocument()) {

View File

@ -447,16 +447,19 @@ public class WebPlayerView extends ViewGroup implements VideoPlayer.VideoPlayerD
.followSslRedirects(true)
.build();
Request.Builder request = new Request.Builder()
.url(url)
Request.Builder request = new Request.Builder().url(url)
.header("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20150101 Firefox/47.0 (Chrome)")
.header("Accept-Language", "en-us,en;q=0.5")
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.header("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
for (Map.Entry<String, String> header : headers.entrySet()) {
if (headers != null) {
request.addHeader(header.getKey(),header.getValue());
for (Map.Entry<String, String> header : headers.entrySet()) {
request.addHeader(header.getKey(), header.getValue());
}
}

View File

@ -59,6 +59,7 @@ import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@ -382,7 +383,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
BottomBuilder builder = new BottomBuilder(getParentActivity());
EditTextBoldCursor[] inputs = new EditTextBoldCursor[2];
EditText[] inputs = new EditText[2];
builder.addTitle(LocaleController.getString("CustomApi", R.string.CustomApi),
true,
@ -394,7 +395,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
builder.doRadioCheck(cell);
for (EditTextBoldCursor input : inputs) input.setVisibility(View.GONE);
for (EditText input : inputs) input.setVisibility(View.GONE);
return Unit.INSTANCE;
@ -406,7 +407,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
builder.doRadioCheck(cell);
for (EditTextBoldCursor input : inputs) input.setVisibility(View.GONE);
for (EditText input : inputs) input.setVisibility(View.GONE);
return Unit.INSTANCE;
@ -418,7 +419,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
builder.doRadioCheck(cell);
for (EditTextBoldCursor input : inputs) input.setVisibility(View.GONE);
for (EditText input : inputs) input.setVisibility(View.GONE);
return Unit.INSTANCE;
@ -431,7 +432,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
builder.doRadioCheck(cell);
for (EditTextBoldCursor input : inputs) input.setVisibility(View.VISIBLE);
for (EditText input : inputs) input.setVisibility(View.VISIBLE);
return Unit.INSTANCE;
@ -449,16 +450,22 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (StrUtil.isBlank(s.toString())) {
NekoXConfig.customAppId = 0;
} else if (!NumberUtil.isInteger(s.toString())) {
inputs[0].setText("0");
} else {
NekoXConfig.customAppId = NumberUtil.parseInt(s.toString());
}
}
@Override
public void afterTextChanged(Editable s) {
NekoXConfig.customAppId = NumberUtil.parseInt(s.toString());
}
});
inputs[1] = builder.addEditText("App Hash");
inputs[1].setInputType(InputType.TYPE_CLASS_TEXT);
inputs[1].setFilters(new InputFilter[]{new InputFilter.LengthFilter(BuildVars.OFFICAL_APP_HASH.length())});
if (StrUtil.isNotBlank(NekoXConfig.customAppHash)) {
inputs[1].setText(NekoXConfig.customAppHash);
}
@ -469,17 +476,17 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
NekoXConfig.customAppHash = s.toString();
}
@Override
public void afterTextChanged(Editable s) {
NekoXConfig.customAppHash = s.toString();
}
});
if (NekoXConfig.customApi <= 2) {
for (EditTextBoldCursor input : inputs) input.setVisibility(View.GONE);
for (EditText input : inputs) input.setVisibility(View.GONE);
}

View File

@ -482,7 +482,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
} else if (id == menu_retest_ping) {
checkProxyList(true);
} else if (id == menu_reorder_by_ping) {
SharedConfig.proxyList = new LinkedList<>(new TreeSet<>(SharedConfig.proxyList));
SharedConfig.proxyList = new LinkedList<>(new TreeSet<>(SharedConfig.getProxyList()));
SharedConfig.saveProxyList();
updateRows(true);
} else if (id == menu_export_json || id == menu_dev_export_public) {
@ -496,7 +496,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
JSONArray proxyArray = new JSONArray();
for (SharedConfig.ProxyInfo info : SharedConfig.proxyList) {
for (SharedConfig.ProxyInfo info : SharedConfig.getProxyList()) {
if (id == menu_dev_export_public) {
@ -724,7 +724,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
} else if (position == hidePublicRow) {
if (NekoConfig.hidePublicProxy && SharedConfig.proxyEnabled && SharedConfig.currentProxy.isPublic) {
if (NekoConfig.hidePublicProxy && SharedConfig.proxyEnabled && SharedConfig.currentProxy != null && SharedConfig.currentProxy.isPublic) {
NotificationCenter.getGlobalInstance().removeObserver(ProxyListActivity.this, NotificationCenter.proxySettingsChanged);
SharedConfig.setCurrentProxy(null);
NotificationCenter.getGlobalInstance().addObserver(ProxyListActivity.this, NotificationCenter.proxySettingsChanged);
@ -1046,7 +1046,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
private void deleteUnavailableProxy() {
for (SharedConfig.ProxyInfo info : new LinkedList<>(SharedConfig.proxyList)) {
for (SharedConfig.ProxyInfo info : SharedConfig.getProxyList()) {
if (info.isPublic) continue;

View File

@ -527,7 +527,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
LocaleController.getString("DebugMenuReloadContacts", R.string.DebugMenuReloadContacts),
LocaleController.getString("DebugMenuResetContacts", R.string.DebugMenuResetContacts),
LocaleController.getString("DebugMenuResetDialogs", R.string.DebugMenuResetDialogs),
BuildVars.DEBUG_VERSION ? LocaleController.getString("DebugMenuDisableLogs", R.string.DebugMenuDisableLogs) : LocaleController.getString("DebugMenuEnableLogs", R.string.DebugMenuEnableLogs),
BuildVars.SAVE_LOG ? LocaleController.getString("DebugMenuDisableLogs", R.string.DebugMenuDisableLogs) : LocaleController.getString("DebugMenuEnableLogs", R.string.DebugMenuEnableLogs),
NekoConfig.residentNotification ? LocaleController.getString("DisableResidentNotification", R.string.DisableResidentNotification) : LocaleController.getString("EnableResidentNotification", R.string.EnableResidentNotification),
LocaleController.getString("DebugMenuClearMediaCache", R.string.DebugMenuClearMediaCache),
LocaleController.getString("DebugMenuCallSettings", R.string.DebugMenuCallSettings),
@ -849,7 +849,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
questionRow = rowCount++;
faqRow = rowCount++;
policyRow = -1;
if (BuildVars.DEBUG_VERSION) {
if (BuildVars.SAVE_LOG) {
helpSectionCell = rowCount++;
debugHeaderRow = rowCount++;
} else {

View File

@ -90,7 +90,6 @@ import java.util.concurrent.atomic.AtomicReference;
import kotlin.Unit;
import tw.nekomimi.nekogram.BottomBuilder;
import tw.nekomimi.nekogram.NekoXConfig;
import tw.nekomimi.nekogram.utils.AlertUtil;
import tw.nekomimi.nekogram.utils.FileUtil;
import tw.nekomimi.nekogram.utils.ShareUtil;
@ -191,6 +190,13 @@ public class StickersActivity extends BaseFragment implements NotificationCenter
currentType = type;
}
private File stickersFile;
public StickersActivity(File stickersFile) {
this(MediaDataController.TYPE_IMAGE);
this.stickersFile = stickersFile;
}
@Override
public boolean onFragmentCreate() {
super.onFragmentCreate();
@ -259,7 +265,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter
@Override
public void didSelectFiles(DocumentSelectActivity activity, ArrayList<String> files, String caption, boolean notify, int scheduleDate) {
activity.finishFragment();
processStickersFile(new File(files.get(0)));
processStickersFile(new File(files.get(0)), false);
}
@Override
@ -275,16 +281,12 @@ public class StickersActivity extends BaseFragment implements NotificationCenter
}
});
if (NekoXConfig.developerMode) {
ActionBarMenu menu = actionBar.createMenu();
ActionBarMenu menu = actionBar.createMenu();
ActionBarMenuItem otherItem = menu.addItem(menu_other, R.drawable.ic_ab_other);
ActionBarMenuItem otherItem = menu.addItem(menu_other, R.drawable.ic_ab_other);
otherItem.addSubItem(menu_export, R.drawable.baseline_file_download_24, LocaleController.getString("ExportStickers", R.string.ExportStickers));
otherItem.addSubItem(menu_import, R.drawable.baseline_playlist_add_24, LocaleController.getString("ImportStickers", R.string.ImportStickers));
}
otherItem.addSubItem(menu_export, R.drawable.baseline_file_download_24, LocaleController.getString("ExportStickers", R.string.ExportStickers));
otherItem.addSubItem(menu_import, R.drawable.baseline_playlist_add_24, LocaleController.getString("ImportStickers", R.string.ImportStickers));
final ActionBarMenu actionMode = actionBar.createActionMode();
selectedCountTextView = new NumberTextView(actionMode.getContext());
@ -390,20 +392,27 @@ public class StickersActivity extends BaseFragment implements NotificationCenter
}
});
if (stickersFile != null) {
processStickersFile(stickersFile, true);
stickersFile = null;
}
return fragmentView;
}
public void processStickersFile(File file) {
public void processStickersFile(File file, boolean exitOnFail) {
if (!file.isFile() || !file.getName().endsWith("nekox-stickers.json")) {
showError("not a stickers file");
showError("not a stickers file", exitOnFail);
return;
} else if (file.length() > 3 * 1024 * 1024L) {
showError("file too large");
showError("file too large", exitOnFail);
return;
@ -432,9 +441,15 @@ public class StickersActivity extends BaseFragment implements NotificationCenter
}
private void showError(String msg) {
private void showError(String msg, boolean exitOnFail) {
AlertUtil.showSimpleAlert(getParentActivity(), LocaleController.getString("InvalidStickersFile", R.string.InvalidStickersFile) + msg);
AlertUtil.showSimpleAlert(getParentActivity(), LocaleController.getString("InvalidStickersFile", R.string.InvalidStickersFile) + msg, (__) -> {
if (exitOnFail) finishFragment();
return Unit.INSTANCE;
});
}
@ -452,7 +467,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter
builder.addCheckItems(new String[]{
LocaleController.getString("StickerSets", R.string.StickerSets),
LocaleController.getString("ArchivedStickers", R.string.ArchivedStickers)
}, (__) -> true,false, (index, text,cell) -> {
}, (__) -> true, false, (index, text, cell) -> {
boolean export;
@ -779,7 +794,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter
if (which == MENU_EXPORT) {
AlertDialog pro = new AlertDialog(getParentActivity(),3);
AlertDialog pro = new AlertDialog(getParentActivity(), 3);
pro.setCanCacnel(false);
pro.show();

View File

@ -4,9 +4,8 @@ import android.content.Context
import android.text.TextUtils
import android.util.TypedValue
import android.view.Gravity
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView
import android.view.ViewGroup
import android.widget.*
import org.telegram.messenger.AndroidUtilities
import org.telegram.messenger.LocaleController
import org.telegram.messenger.R
@ -17,22 +16,35 @@ import org.telegram.ui.Cells.HeaderCell
import org.telegram.ui.Cells.RadioButtonCell
import org.telegram.ui.Cells.ShadowSectionCell
import org.telegram.ui.Cells.TextCheckCell
import org.telegram.ui.Components.EditTextBoldCursor
import org.telegram.ui.Components.HintEditText
import org.telegram.ui.Components.LayoutHelper
import java.util.*
class BottomBuilder(val ctx: Context) {
val builder = BottomSheet.Builder(ctx,true)
val builder = BottomSheet.Builder(ctx, true)
private val rootView = LinearLayout(ctx).apply {
orientation = LinearLayout.VERTICAL
}
private val _root = LinearLayout(ctx).apply {
addView(ScrollView(ctx).apply {
addView(this@BottomBuilder.rootView)
isFillViewport = true
isVerticalScrollBarEnabled = false
},LinearLayout.LayoutParams(-1,-1))
builder.setCustomView(this)
}
private val buttonsView by lazy {
FrameLayout(ctx).apply {
@ -263,21 +275,18 @@ class BottomBuilder(val ctx: Context) {
}
fun addEditText(hintText: String): EditTextBoldCursor {
fun addEditText(hintText: String): EditText {
return EditTextBoldCursor(ctx).apply {
return EditText(ctx).apply {
setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18f)
setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14f)
setTextColor(Theme.getColor(Theme.key_dialogTextBlack))
hint = hintText
setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader))
isSingleLine = true
isFocusable = true
setTransformHintToHeader(true)
setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3))
setBackgroundDrawable(null)
this@BottomBuilder.rootView.addView(this, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, -2, Gravity.LEFT or Gravity.TOP,AndroidUtilities.dp(14F),AndroidUtilities.dp(4F),0,AndroidUtilities.dp(4F)))
this@BottomBuilder.rootView.addView(this, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, -2, if (LocaleController.isRTL) Gravity.RIGHT else Gravity.LEFT, AndroidUtilities.dp(8F), 0, 0, 0))
}

View File

@ -36,6 +36,7 @@ import tw.nekomimi.nekogram.utils.AlertUtil;
import tw.nekomimi.nekogram.utils.FileUtil;
import tw.nekomimi.nekogram.utils.LocaleUtil;
import tw.nekomimi.nekogram.utils.ShareUtil;
import tw.nekomimi.nekogram.utils.UIUtil;
import tw.nekomimi.nekogram.utils.ZipUtil;
public class NekoXSettingActivity extends BaseFragment {
@ -150,7 +151,9 @@ public class NekoXSettingActivity extends BaseFragment {
pro.show();
LocaleUtil.fetchAndExportLang(currentAccount, () -> {
UIUtil.runOnIoDispatcher(() -> {
LocaleUtil.fetchAndExportLang(currentAccount);
File zipFile = new File(ApplicationLoader.applicationContext.getCacheDir(), "languages.zip");

View File

@ -494,7 +494,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
JSONArray proxyArray = new JSONArray();
for (SharedConfig.ProxyInfo info : SharedConfig.proxyList) {
for (SharedConfig.ProxyInfo info : SharedConfig.getProxyList()) {
if (id == menu_dev_export_public) {

View File

@ -3,7 +3,6 @@ package tw.nekomimi.nekogram
import android.content.Context
import com.v2ray.ang.dto.AngConfig
import org.telegram.messenger.ApplicationLoader
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.ServerSocket
import kotlin.random.Random
@ -19,7 +18,7 @@ object ProxyManager {
var port = pref.getInt(hash, -1)
if (!isTcpPortAvailable(port)) {
if (!isProxyAvailable(port)) {
port = mkNewPort()
@ -38,7 +37,7 @@ object ProxyManager {
var port = pref.getInt(hash, -1)
if (!isTcpPortAvailable(port)) {
if (!isProxyAvailable(port)) {
port = mkNewPort()
@ -57,7 +56,7 @@ object ProxyManager {
var port = pref.getInt(hash, -1)
if (!isTcpPortAvailable(port)) {
if (!isProxyAvailable(port)) {
port = mkNewPort()
@ -69,19 +68,31 @@ object ProxyManager {
}
@JvmStatic
fun mkNewPort() = Random.nextInt(2048, 32768)
private fun mkNewPort() = Random.nextInt(2048, 32768)
@JvmStatic
open fun isTcpPortAvailable(port: Int): Boolean {
try {
ServerSocket(port).use {
it.reuseAddress = true
return true
}
} catch (ex: Exception) {
fun isProxyAvailable(port: Int): Boolean {
if (port !in 2048 until 32768) return false
runCatching {
val server = ServerSocket()
server.bind(InetSocketAddress("127.0.0.1",port))
server.close()
Thread.sleep(1000L)
}.onFailure {
return false
}
return true
}
}

View File

@ -1,6 +1,5 @@
package tw.nekomimi.nekogram
import android.util.Log
import com.google.gson.Gson
import com.v2ray.ang.V2RayConfig
import com.v2ray.ang.V2RayConfig.SOCKS_PROTOCOL
@ -19,6 +18,7 @@ import org.telegram.messenger.FileLog
import org.telegram.messenger.LocaleController
import org.telegram.messenger.R
import kotlin.concurrent.thread
import kotlin.random.Random
class VmessLoader {
@ -103,7 +103,7 @@ class VmessLoader {
} else {
var result = server.replace(VMESS_PROTOCOL, "")
result = Utils.decode(result)
result = Utils.decodeJson(result)
if (result.isBlank()) {
error("invalid url format")
}
@ -312,12 +312,12 @@ class VmessLoader {
var path = ""
var host = ""
val lstParameter = vmess.requestHost.split(";")
if (lstParameter.size > 0) {
path = lstParameter.get(0).trim()
if (lstParameter.isNotEmpty()) {
path = lstParameter[0].trim()
}
if (lstParameter.size > 1) {
path = lstParameter.get(0).trim()
host = lstParameter.get(1).trim()
path = lstParameter[0].trim()
host = lstParameter[1].trim()
}
vmess.path = path
vmess.requestHost = host
@ -370,29 +370,46 @@ class VmessLoader {
}
fun initConfig(config: VmessBean, port: Int) {
lateinit var bean: VmessBean
point.configureFileContent = V2rayConfigUtil.getV2rayConfig(config, port).content
point.domainName = V2rayConfigUtil.currDomain
fun initConfig(config: VmessBean) {
Log.d("nekox", point.configureFileContent)
Log.d("nekox", "domainName: " + point.domainName)
this.bean = config
}
fun start() {
fun start(): Int {
if (point.isRunning) return
var retry = 3
runCatching {
do {
point.runLoop(true)
try {
}.onFailure {
val port = Random.nextInt(4096, 32768)
FileLog.e(it)
point.configureFileContent = V2rayConfigUtil.getV2rayConfig(bean, port).content
point.domainName = V2rayConfigUtil.currDomain
}
point.runLoop(true)
return port
} catch (e: Exception) {
retry --
if (retry <= 0) {
FileLog.e(e)
return -1
}
}
} while (true)
}

View File

@ -28,14 +28,21 @@ object AlertUtil {
})
@JvmStatic
fun showSimpleAlert(ctx: Context?, text: String) = UIUtil.runOnUIThread(Runnable {
@JvmOverloads
fun showSimpleAlert(ctx: Context?, text: String, listener: ((AlertDialog.Builder) -> Unit)? = null) = UIUtil.runOnUIThread(Runnable {
val builder = AlertDialog.Builder(ctx ?: ApplicationLoader.applicationContext)
builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX))
builder.setMessage(text)
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK)) { _,_ ->
listener?.invoke(builder)
builder.dismissRunnable.run()
}
builder.show()
@ -135,8 +142,8 @@ object AlertUtil {
})
})
fun showTimePicker(ctx: Context,title: String,callback: (Long) -> Unit) {
fun showTimePicker(ctx: Context, title: String, callback: (Long) -> Unit) {
ctx.setTheme(R.style.Theme_TMessages)
@ -153,7 +160,7 @@ object AlertUtil {
minValue = 0
maxValue = 60
},LinearLayout.LayoutParams(-2,-2).apply {
}, LinearLayout.LayoutParams(-2, -2).apply {
weight = 1F
@ -164,7 +171,7 @@ object AlertUtil {
minValue = 0
maxValue = 60
},LinearLayout.LayoutParams(-2,-2).apply {
}, LinearLayout.LayoutParams(-2, -2).apply {
weight = 1F

View File

@ -28,9 +28,13 @@ object FileUtil {
}
@JvmStatic
fun delete(file: File) {
fun delete(file: File?) {
file.deleteRecursively()
runCatching {
file?.deleteRecursively()
}
}

View File

@ -19,7 +19,7 @@ object LocaleUtil {
val cacheDir = File(ApplicationLoader.applicationContext.cacheDir, "builtIn_lang_export")
@JvmStatic
fun fetchAndExportLang(account: Int,callback: Runnable) {
fun fetchAndExportLang(account: Int) = runBlocking {
delete(cacheDir)
initDir(cacheDir)
@ -38,15 +38,15 @@ object LocaleUtil {
lang_code = localeInfo.getBaseLangCode()
}, { response, _ ->
val count = finish.decrementAndGet()
if (response is TL_langPackDifference) {
LocaleController.getInstance().saveRemoteLocaleStrings(localeInfo, response, account)
localeInfo.pathToBaseFile.copyTo(File(cacheDir,localeInfo.pathToBaseFile.name))
}
if (count == 0) callback.run()
localeInfo.pathToBaseFile.copyTo(File(cacheDir,localeInfo.pathToBaseFile.name))
finish.decrementAndGet()
}, ConnectionsManager.RequestFlagWithoutLogin)
@ -58,19 +58,22 @@ object LocaleUtil {
lang_code = localeInfo.langCode
}, { response, _ ->
val count = finish.decrementAndGet()
if (response is TL_langPackDifference) {
LocaleController.getInstance().saveRemoteLocaleStrings(localeInfo, response, account)
localeInfo.getPathToFile().copyTo(File(cacheDir,localeInfo.getPathToFile().name))
}
if (count == 0) callback.run()
localeInfo.getPathToFile().copyTo(File(cacheDir,localeInfo.getPathToFile().name))
finish.decrementAndGet()
}, ConnectionsManager.RequestFlagWithoutLogin)
}
while (finish.get() != 0) delay(100L)
}
}

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="UseOfficalId">متنكر كتطبيق رسمي</string>
<string name="UseOfficalIdNotice">تسجيل الدخول باستخدام معرف التطبيق الرسمي، إذا كنت غير قادر على التسجيل أو تسجيل الدخول، قد يساعد ذلك.\n\nملاحظة: لن يعمل fcm إذا كنت تستخدم إصدار الإصدار.</string>
<string name="ChangeTranslateProvider">تغيير المزود</string>
<string name="NekoXUpdatesChannel">قناة تحديثات Nekox</string>
<string name="ShowIdAndDc">إظهار المعرف / dc في الملف الشخصي</string>
@ -108,10 +106,6 @@
<string name="EnableDeveloperMode">تفعيل وضع المطور</string>
<string name="DisableDeveloperMode">تعطيل وضع المطور</string>
<string name="DeveloperSettings">إعدادات المطور</string>
<string name="DisableFlagSecure">تعطيل العلامة الآمنة</string>
<string name="DisableScreenshotDetection">تعطيل الكشف عن لقطة الشاشة</string>
<string name="LoginSettings">إعدادات الدخول</string>
<string name="ShowTestBackend">إظهار خلفية الاختبار</string>
<string name="ShowBotLogin">إظهار تسجيل الدخول للبوت</string>
<string name="NekoXFaq">أسئلة NekoX الشائعة</string>
</resources>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="UseOfficalId">ورود به عنوان تلگرام رسمی</string>
<string name="UseOfficalIdNotice">با استفاده از شناسه رسمی برنامه وارد شوید ، اگر قادر به ثبت نام یا ورود به سیستم نیستید ، این ممکن است کمک کند. توجه: اگر از آخرین نسخه استفاده می کنید ، fcm کار نخواهد کرد.</string>
<string name="ChangeTranslateProvider">تغییر ارائه دهنده خدمات</string>
<string name="NekoXUpdatesChannel">کانال بروزرسانی NekoX</string>
<string name="ShowIdAndDc">نمایش آیدی کاربر در پروفایل</string>
@ -29,7 +27,7 @@
<string name="FilterNameGroupsDescription">فقط پیامهای گفتگو های گروهی</string>
<string name="FilterNameChannels">کانال ها</string>
<string name="FilterNameChannelsDescription">فقط پیام های کانال ها</string>
<string name="FilterNameBots">ربات ها</string>
<string name="FilterNameBots">ربات</string>
<string name="FilterNameBotsDescription">فقط پیام های ربات ها</string>
<string name="FilterNameUnmuted">صدا دار</string>
<string name="FilterNameUnmutedDescription">فقط پیام های گفتگو های صدا دار</string>
@ -56,13 +54,13 @@
<string name="DeleteAllInChat">حذف همه در این گفتگو</string>
<string name="DeleteAllInChatAlert">هشدار! با این کار ، **تمام پیام ها** در این گفتگو برای همه شرکت کنندگان حذف می شود.</string>
<string name="UnblockAll">رفع مسدودی همه</string>
<string name="UnblockAllWarn">آیا شما از رفع مسدود**همه ی کاربران و ربات ها**اطمینان دارید؟</string>
<string name="UnblockAllWarn">آیا شما از رفع مسدود**همه ی کاربران و ربات ها**اطمینان دارید?</string>
<string name="BlockedListEmpty">شما هیچ فردی را مسدود نکرده اید :)</string>
<string name="ProxyTypeVmess">پروکسی Vmess</string>
<string name="AddProxySocks5">افزودن پروکسی Socks5</string>
<string name="AddProxyTelegram">افزودن پروکسی MTproto</string>
<string name="AddProxyVmess">افزودن پروکسی Vmess</string>
<string name="AddProxySS">افزودن شادوساکس SS</string>
<string name="AddProxySS">افزودن شادوساکس Ss</string>
<string name="AddProxySSR">افزودن شادوساکس SSR</string>
<string name="EditProxy">ویرایش پروکسی</string>
<string name="ShareProxy">اشتراک گذاری پروکسی</string>
@ -70,21 +68,21 @@
<string name="ProxyInfoVmess">تنظیمات پروکسی Vmess</string>
<string name="VmessUserId">آیدی کاربر</string>
<string name="VmessAlterId">آیدی عددی</string>
<string name="VmessSecurity">Security</string>
<string name="VmessSecurity">امنیت</string>
<string name="VmessNetwork">Network</string>
<string name="VmessHeadType">Head Type</string>
<string name="VmessRequestHost">Request Host / QUIC Security</string>
<string name="VmessPath">Path / QUIC Key</string>
<string name="VmessTls">Use TLS</string>
<string name="VmessPath">درخواست میزبان / امنیت QUIC</string>
<string name="VmessTls">از TLS استفاده کنید</string>
<string name="ProxyInfoSS">تنظیمات شادوساکس ss</string>
<string name="SSPassword">Password</string>
<string name="SSMethod">Encrypt Method</string>
<string name="SSPassword">رمز</string>
<string name="SSMethod">روش رمز گذاری</string>
<string name="ProxyInfoSSR">تنظیمات شادوساکس ssʀ</string>
<string name="SSRProtocol">Protocol</string>
<string name="SSRProtocolParams">Protocol Params</string>
<string name="SSRProtocol">پروتکل</string>
<string name="SSRProtocolParams">پارامترهای پروتکل</string>
<string name="SSRObfs">Obfs</string>
<string name="SSRObfsParam">Obfs Param</string>
<string name="ProxyRemarks">Remarks</string>
<string name="ProxyRemarks">ملاحضات</string>
<string name="RetestPing">تست مجدد پینگ سرورها</string>
<string name="ReorderByPing">مرتب سازی براساس پینگ</string>
<string name="ExportProxies">استخراج فایل سرورها</string>
@ -108,10 +106,6 @@
<string name="EnableDeveloperMode">فعالسازی حالت توسعه دهنده</string>
<string name="DisableDeveloperMode">غیرفعال‌سازی حالت توسعه دهنده</string>
<string name="DeveloperSettings">تنظیمات توسعه دهنده</string>
<string name="DisableFlagSecure">غیرفعال‌سازی پرچم امنیتی</string>
<string name="DisableScreenshotDetection">غیر فعال کردن شناسایی اسکرین‌شات</string>
<string name="LoginSettings">تنظیمات ورود به سیستم</string>
<string name="ShowTestBackend">نمایش آزمایشی پس زمینه</string>
<string name="ShowBotLogin">دیدن ربات وارد شده</string>
<string name="NekoXFaq">پرسش های متداول NekoX</string>
</resources>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="UseOfficalId">公式アプリに偽装する</string>
<string name="UseOfficalIdNotice">公式アプリのIDを使用してログインします。登録やログインができない時には役に立つかもしれません。\n\n注意:リリースバージョンを使用しているとFCMは動作しません。</string>
<string name="ChangeTranslateProvider">プロバイダを変更</string>
<string name="NekoXUpdatesChannel">NekoX アップデートチャンネル</string>
<string name="UseDefaultTheme">デフォルトテーマを使用 *</string>
@ -103,9 +101,6 @@
<string name="EnableDeveloperMode">開発者モードを有効にする</string>
<string name="DisableDeveloperMode">開発者モードを無効にする</string>
<string name="DeveloperSettings">開発者設定</string>
<string name="DisableScreenshotDetection">スクリーンショットの検出を無効にする</string>
<string name="LoginSettings">ログイン設定</string>
<string name="ShowTestBackend">テストバックエンドを表示</string>
<string name="ShowBotLogin">ボットログインを表示</string>
<string name="NekoXFaq">NekoX FAQ</string>
</resources>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="UseOfficalId">Disfarça como aplicativo oficial</string>
<string name="UseOfficalIdNotice">Faça login usando o ID do aplicativo oficial. Se não conseguir se registrar ou fazer login, isso pode ajudar. \n\nNota: o fcm não funcionará se você estiver usando a versão de lançamento.</string>
<string name="ChangeTranslateProvider">Alterar Provedor</string>
<string name="NekoXUpdatesChannel">Canal de atualizações do NekoX</string>
<string name="ShowIdAndDc">Mostrar ID/DC no perfil</string>
@ -108,10 +106,6 @@
<string name="EnableDeveloperMode">Ativar modo de desenvolvedor</string>
<string name="DisableDeveloperMode">Desativar modo desenvolvedor</string>
<string name="DeveloperSettings">Configurações de desenvolvedor</string>
<string name="DisableFlagSecure">Desativar sinalização segura</string>
<string name="DisableScreenshotDetection">Desativar detecção de captura de tela</string>
<string name="LoginSettings">Configurações de login</string>
<string name="ShowTestBackend">Mostrar back-end de teste</string>
<string name="ShowBotLogin">Mostrar Login do Bot</string>
<string name="NekoXFaq">FAQ do NekoX</string>
</resources>

View File

@ -1,7 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="UseOfficalId">假装是官方应用</string>
<string name="UseOfficalIdNotice">登录时将自己标识为官方应用,如果您无法注册或登录,这可能会有帮助。\n\n注意如果您正在使用 release 版本,谷歌云推送将无法工作。</string>
<string name="CustomApi">自定义 Api</string>
<string name="UseCustomApiNotice">使用自定义 Api 登录,如果您无法注册或登录,这可能会有帮助。\n\n注意如果您正在使用 release 版本,谷歌云推送将无法工作。</string>
<string name="CustomApiNo">不使用自定义 API</string>
<string name="CustomApiOffical">Telegram Android</string>
<string name="CustomApiTGX">Telegram X</string>
<string name="CustomApiInput">手动输入</string>
<string name="AllowFlashCall">允许电话呼叫</string>
<string name="ChangeTranslateProvider">修改翻译源</string>
<string name="NekoXUpdatesChannel">NekoX 更新频道</string>
<string name="ShowIdAndDc">在个人资料中显示 id / dc</string>
@ -11,6 +16,7 @@
<string name="PrivacyNoticePhoneVisible">检测到您的手机号码对任何人都可见, 这可能会导致政府控制的黑客找到您的真实身份,请关闭它!</string>
<string name="PrivacyNoticeAddByPhone">检测到您没有被关闭“允许通过电话号码找到我”设置, 这可能会导致政府控制的黑客找到您的真实身份,请关闭它!</string>
<string name="PrivacyNoticeP2p">检测到您没有关闭“允许 P2p 通话”设置, 这可能会导致政府控制的黑客找到您的真实身份,请关闭它!</string>
<string name="PrivacyNotice2fa">检测到您没有设置密码,这可能会导致政府控制的黑客找到您的真实身份,请设置一个!</string>
<string name="ApplySuggestion">应用</string>
<string name="DoNotRemindAgain">不再提醒</string>
<string name="RemoveTitleEmoji">移除标题中的表情</string>
@ -91,6 +97,12 @@
<string name="ImportProxies">从文件导入服务器列表</string>
<string name="ImportProxyList">导入代理服务器列表</string>
<string name="ImportProxyListConfirm">您确定要**导入代理服务器列表**吗?</string>
<string name="ExportStickers">导出贴纸集</string>
<string name="ImportStickers">从文件导入贴纸集</string>
<string name="ImportStickersList">导入贴纸集</string>
<string name="ImportStickersConfirm">您确定要**导入贴纸集**吗?</string>
<string name="StickerSets">贴纸集</string>
<string name="InvalidStickersFile">无效的贴纸集文件: </string>
<string name="InvalidProxyFile">无效的代理列表文件: </string>
<string name="ImportedProxies">已导入的代理服务器: </string>
<string name="ErrorsInImport">导入错误: </string>
@ -108,10 +120,6 @@
<string name="EnableDeveloperMode">启用开发者模式</string>
<string name="DisableDeveloperMode">禁用开发者模式</string>
<string name="DeveloperSettings">开发者设置</string>
<string name="DisableFlagSecure">禁用安全标记</string>
<string name="DisableScreenshotDetection">禁用截屏检测</string>
<string name="LoginSettings">登录设置</string>
<string name="ShowTestBackend">显示连接到测试后端</string>
<string name="ShowBotLogin">显示机器人秘钥登录</string>
<string name="NekoXFaq">NekoX 常见问题</string>
</resources>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="UseOfficalId">假裝是官方應用</string>
<string name="UseOfficalIdNotice">登錄時將自己標識為官方應用,如果您無法註冊或登錄,這可能會有幫助。 \n\n注意如果您正在使用 release 版本,谷歌云推送將無法工作。</string>
<string name="ChangeTranslateProvider">修改翻譯源</string>
<string name="NekoXUpdatesChannel">NekoX 更新頻道</string>
<string name="ShowIdAndDc">在個人資料中顯示 id / dc</string>
@ -108,10 +106,6 @@
<string name="EnableDeveloperMode">啓用開發人員模式</string>
<string name="DisableDeveloperMode">禁用開發人員模式</string>
<string name="DeveloperSettings">開發人員設定</string>
<string name="DisableFlagSecure">禁用安全標記</string>
<string name="DisableScreenshotDetection">禁用截屏檢測</string>
<string name="LoginSettings">登錄設定</string>
<string name="ShowTestBackend">顯示連接到測試後端</string>
<string name="ShowBotLogin">顯示機器人秘鑰登錄</string>
<string name="NekoXFaq">NekoX 常見問題</string>
</resources>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="UseOfficalId">偽裝成官方客戶端</string>
<string name="UseOfficalIdNotice">登錄時將自己標識為官方客戶端,如果您無法註冊或登錄,這可能會有幫助。 \n\n注意如果您正在使用 release 版本,谷歌雲推送將無法工作。</string>
<string name="ChangeTranslateProvider">修改翻譯源</string>
<string name="NekoXUpdatesChannel">NekoX 更新頻道</string>
<string name="ShowIdAndDc">在個人資料中顯示 id / dc</string>
@ -108,10 +106,6 @@
<string name="EnableDeveloperMode">啓用開發人員模式</string>
<string name="DisableDeveloperMode">禁用開發人員模式</string>
<string name="DeveloperSettings">開發人員設定</string>
<string name="DisableFlagSecure">禁用安全標記</string>
<string name="DisableScreenshotDetection">禁用截屏檢測</string>
<string name="LoginSettings">登錄設定</string>
<string name="ShowTestBackend">顯示連接到測試後端</string>
<string name="ShowBotLogin">顯示機器人秘鑰登錄</string>
<string name="NekoXFaq">NekoX 常見問題</string>
</resources>

View File

@ -134,6 +134,9 @@
<string name="ExportStickers">Export Stickers</string>
<string name="ImportStickers">Import stickers from file</string>
<string name="ImportStickersList">Import stickers</string>
<string name="ImportStickersConfirm">Are you sure you want to **import stickers**?</string>
<string name="StickerSets">Sticker Sets</string>
<string name="InvalidStickersFile">Invalid stickers file: </string>

View File

@ -6,10 +6,10 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.71"
classpath 'com.android.tools.build:gradle:3.6.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72"
classpath 'com.google.gms:google-services:4.3.3'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta03'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04'
}
}