diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 3251d3bf..0e20bfa1 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -634,5 +634,14 @@ "anniversary_tweet": { "message": "Do you remember when you joined Twitter? I do!\n#MyTwitterAnniversary" }, "you_shared_tweet": { "message": "You shared a tweet" }, "user_shared_tweet": { "message": "$NAME$ shared a tweet", "placeholders": { "name": { "content": "Display Name" } } }, - "transition_profile_banner": { "message": "Use transition on profile banner" } -} \ No newline at end of file + "transition_profile_banner": { "message": "Use transition on profile banner" }, + "custom_downloadtemplate": { "message": "Custom download template" }, + "custom_downloadtemplate_text": { "message": "Allows you to customize the names of the files when downloading a tweet's media." }, + "save_downloadtemplate": { "message": "Save download template" }, + "custom_downloadtemplate_hintName1": { "message": "{user_name}: User's name." }, + "custom_downloadtemplate_hintName2": { "message": "{user_screen_name}: User's account name. (Example: @dril)" }, + "custom_downloadtemplate_hintTime": { "message": "{timestamp}: Tweet's post date & time." }, + "custom_downloadtemplate_hintExtension": { "message": "{extension}: Downloaded tweet's file extension." }, + "custom_downloadtemplate_hintID": { "message": "{id}: Tweet's ID." }, + "custom_downloadtemplate_hintIndex": { "message": "{index}: Index for each file to download. (for posts with multiple media)" } +} diff --git a/_locales/tr/messages.json b/_locales/tr/messages.json index e53ba0ca..e317e0a4 100644 --- a/_locales/tr/messages.json +++ b/_locales/tr/messages.json @@ -596,7 +596,7 @@ "message": "Varsayılan bağlantı rengi" }, "font": { - "message": "Font" + "message": "Yazı tipi" }, "color_sync": { "message": "Bağlantı rengi eşitlenimi" @@ -857,10 +857,10 @@ } }, "last_searches": { - "message": "Last searches" + "message": "Son aramalar" }, "saved_searches": { - "message": "Saved searches" + "message": "Kaydedilmiş aramalar" }, "everyone": { "message": "Herkese açık", @@ -963,7 +963,7 @@ "message": "Konuşmayı susturmayı geri al" }, "no_big_font": { - "message": "Kısa/popüler tweetler için büyük fontu devre dışı bırak" + "message": "Kısa/popüler tweetler için büyük yazı tipini devre dışı bırak" }, "emoji": { "message": "Emoji" @@ -1401,7 +1401,7 @@ "description": "You should probably use word 'Profile' in your language" }, "tweet_text_font": { - "message": "Tweet yazı fontu" + "message": "Tweet yazı tipi" }, "use_old_default_profile": { "message": "Varsayılan profil fotoğrafını yumurta yap" @@ -1576,7 +1576,7 @@ "message": "Karanlık mod değişkenleri" }, "css_theme_hint": { - "message": "Lütfen 'göz-kanatıcı' veya diğer herhangi rahatsız edici şeyler yapmayın. (Örneğin takip butonunu çok büyük yapmak gibi), bunun yüzünden erişimini kaybedersin.

Senin CSS'in kullanıcının ayarladığı temanın üzerine yazılır.

Resimleri için sadece i.imgur.com, fontlar için de sadece fonts.googleapis.com kullanabilirsin (veya 'daki fontlar).

You can see list of CSS variables here.

To target specific theme you can use .body-dark, .body-pitch-black (pitch black mode will also include .body-dark) and .body-light classes." + "message": "Lütfen 'göz-kanatıcı' veya diğer herhangi rahatsız edici şeyler yapmayın. (Örneğin takip butonunu çok büyük yapmak gibi), bunun yüzünden erişimini kaybedersin.

Senin CSS'in kullanıcının ayarladığı temanın üzerine yazılır.

Resimleri için sadece i.imgur.com, yazı tipleri için de sadece fonts.googleapis.com kullanabilirsin (veya 'daki yazı tiplerini).

You can see list of CSS variables here.

To target specific theme you can use .body-dark, .body-pitch-black (pitch black mode will also include .body-dark) and .body-light classes." }, "profile_colors_moved": { "message": "Renk senkronizasyonunu profiline bağla (Edit butonunun solundaki kalem butonu)." @@ -1817,7 +1817,7 @@ "message": "Eklenti uyumluluk modu (Başka bir eklentinin OldTwitter ile aynı anda çalışmasını istiyorsanız etkinleştirin, eğer eklenti hala çalışmıyorsa bunu kapatın (büyük ihtimalle çalışmayacak), çünkü bu seçenek sayfayı kastırabilir)" }, "enter_custom_font_name": { - "message": "Özel font ismi girin" + "message": "Özel yazı tipi ismi girin" }, "disable_data_saver": { "message": "Veri kaydediciyi mobil verideyken kapatın", diff --git a/layouts/settings/index.html b/layouts/settings/index.html index 44d6adeb..ed42d072 100644 --- a/layouts/settings/index.html +++ b/layouts/settings/index.html @@ -399,6 +399,20 @@

__MSG_custom_css__




+

__MSG_custom_downloadtemplate__


+ __MSG_custom_downloadtemplate_text__
+
__MSG_custom_downloadtemplate_hintName1__ +
__MSG_custom_downloadtemplate_hintName2__ +
__MSG_custom_downloadtemplate_hintTime__ +
__MSG_custom_downloadtemplate_hintExtension__ +
__MSG_custom_downloadtemplate_hintID__ +
__MSG_custom_downloadtemplate_hintIndex__ +

+
+ +
+ +

__MSG_advanced_options__


@@ -443,4 +457,4 @@

__MSG_who_to_follow__


- \ No newline at end of file + diff --git a/layouts/settings/script.js b/layouts/settings/script.js index 29f61af5..a26e1c8c 100644 --- a/layouts/settings/script.js +++ b/layouts/settings/script.js @@ -277,6 +277,8 @@ setTimeout(async () => { let disableFindHotkey = document.getElementById('disable-find-hotkey'); let customCSS = document.getElementById('custom-css'); let customCSSSave = document.getElementById('custom-css-save'); + let customDownloadTemplate = document.getElementById('custom-download'); + let customDownloadTemplateSave = document.getElementById('custom-download-save'); let savePreferredQuality = document.getElementById('save-preferred-quality'); let roundAvatars = document.getElementById('round-avatars-switch'); let modernUI = document.getElementById('modern-ui-switch'); @@ -913,6 +915,14 @@ setTimeout(async () => { console.error("Error saving CSS to DB:", error); }); }); + customDownloadTemplateSave.addEventListener('click', () => { + let val = customDownloadTemplate.value; + + vars.customDownloadTemplate = val; + chrome.storage.sync.set({ + customDownloadTemplate: val + }, () => { }); + }); autotranslateLanguageList.addEventListener('change', () => { addAutotranslateLanguage.disabled = autotranslateLanguageList.value === 'select'; }); @@ -1053,6 +1063,7 @@ setTimeout(async () => { writeCSSToDB(vars.customCSS) } customCSS.value = await readCSSFromDB(); + customDownloadTemplate.value = vars.customDownloadTemplate; document.getElementById('stt-div').hidden = vars.timelineType !== 'algo' && vars.timelineType !== 'algov2'; savePreferredQuality.checked = !!vars.savePreferredQuality; showOriginalImages.checked = !!vars.showOriginalImages; @@ -1288,4 +1299,4 @@ setTimeout(async () => { setInterval(updateUserData, 60000 * 3); setInterval(() => renderDiscovery(false), 60000 * 15); setInterval(renderTrends, 60000 * 5); -}, 50); \ No newline at end of file +}, 50); diff --git a/scripts/config.js b/scripts/config.js index c953f2a2..2b6e83ee 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -32,7 +32,7 @@ async function loadVars() { 'acknowledgedCustomizationButton', 'modernUI', 'showExactValues', 'hideTimelineTypes', 'autotranslateLanguages', 'autotranslationMode', 'muteVideos', 'dontPauseVideos', 'showUserPreviewsOnMobile', 'systemDarkMode', 'localizeDigit', 'disableRetweetHotkey', 'disableLikeHotkey', 'disableFindHotkey', 'extensionCompatibilityMode', 'disableDataSaver', 'disableAcceptType', - 'showUserFollowerCountsInLists', 'showQuoteCount', 'hideUnfollowersPage', 'transitionProfileBanner' + 'showUserFollowerCountsInLists', 'showQuoteCount', 'hideUnfollowersPage', 'transitionProfileBanner', 'customDownloadTemplate' ], data => { // default variables if(typeof(data.linkColorsInTL) !== 'boolean') { @@ -83,6 +83,12 @@ async function loadVars() { customCSSVariables: '' }, () => {}); } + if(typeof(data.customDownloadTemplate) !== 'string') { + data.customDownloadTemplate = ''; + chrome.storage.sync.set({ + customDownloadTemplate: '' + }, () => {}); + } if(typeof(data.copyLinksAs) !== 'string') { data.copyLinksAs = 'twitter.com'; chrome.storage.sync.set({ @@ -240,4 +246,4 @@ async function loadVars() { }; console.log(1, vars); -loadVars(); \ No newline at end of file +loadVars(); diff --git a/scripts/helpers.js b/scripts/helpers.js index 8a8364d0..f9772b85 100644 --- a/scripts/helpers.js +++ b/scripts/helpers.js @@ -3595,8 +3595,22 @@ async function appendTweet(t, timelineContainer, options = {}) { let extension = url.pathname.split('.').pop(); let _index = t.extended_entities.media.length > 1 ? "_"+(index+1) : ""; let filename = `${t.user.screen_name}_${ts}_${t.id_str}${_index}.${extension}`; - a.download = filename; + let filename_template = vars.customDownloadTemplate; + + // use the filename from the user's custom download template, if any + if(filename_template && (filename_template.length > 0)) { + const filesave_map = { + "user_screen_name": t.user.screen_name, + "user_name": t.user.name, + "extension": extension, + "timestamp": ts, + "id": t.id_str, + "index": _index + }; + filename = filename_template.replace(/\{([\w]+)\}/g, (_, key) => filesave_map[key]); + } + a.download = filename; a.click(); a.remove(); }).catch(e => { diff --git a/scripts/tweetviewer.js b/scripts/tweetviewer.js index 61629644..1cf837ec 100644 --- a/scripts/tweetviewer.js +++ b/scripts/tweetviewer.js @@ -2458,8 +2458,28 @@ class TweetViewer { downloading = false; let a = document.createElement('a'); a.href = URL.createObjectURL(blob); - a.download = media.type === 'photo' ? media.media_url_https.split('/').pop() : media.video_info.variants[0].url.split('/').pop(); - a.download = a.download.split('?')[0]; + + let ts = new Date(t.created_at).toISOString().split("T")[0]; + let extension = url.split('.').pop(); + //let _index = t.extended_entities.media.length > 1 ? "_"+(index+1) : ""; + let _index = ""; + let filename = `${t.user.screen_name}_${ts}_${t.id_str}${_index}.${extension}`; + let filename_template = vars.customDownloadTemplate; + + // use the filename from the user's custom download template, if any + if(filename_template && (filename_template.length > 0)) { + const filesave_map = { + "user_screen_name": t.user.screen_name, + "user_name": t.user.name, + "extension": extension, + "timestamp": ts, + "id": t.id_str, + "index": _index + }; + filename = filename_template.replace(/\{([\w]+)\}/g, (_, key) => filesave_map[key]); + } + + a.download = filename; a.click(); a.remove(); }).catch(e => {