diff --git a/package.json b/package.json index 7a240a87..c49adf8e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cobalt", "description": "save what you love", - "version": "7.8.6", + "version": "7.9", "author": "wukko", "exports": "./src/cobalt.js", "type": "module", diff --git a/src/config.json b/src/config.json index 91922a5e..923f4d7b 100644 --- a/src/config.json +++ b/src/config.json @@ -90,7 +90,8 @@ "mp4": ["-c:v", "copy", "-c:a", "copy", "-movflags", "faststart+frag_keyframe+empty_moov"], "copy": ["-c:a", "copy"], "audio": ["-ar", "48000", "-ac", "2", "-b:a", "320k"], - "m4a": ["-movflags", "frag_keyframe+empty_moov"] + "m4a": ["-movflags", "frag_keyframe+empty_moov"], + "gif": ["-vf", "scale=-1:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse", "-loop", "0"] }, "sponsors": [{ "name": "royale", diff --git a/src/front/cobalt.css b/src/front/cobalt.css index ebc77223..8aa8e86b 100644 --- a/src/front/cobalt.css +++ b/src/front/cobalt.css @@ -107,7 +107,7 @@ a { color: var(--accent-subtext); } .switches::-webkit-scrollbar, -#popup-content::-webkit-scrollbar { +.popup-content::-webkit-scrollbar { display: none; } :focus-visible { @@ -450,23 +450,23 @@ button:active, .popup.small.visible { transform: translate(-50%, -50%); } -.popup.small #popup-header-contents, +.popup.small .popup-header-contents, .popup.small .popup-content-inner, -.popup.small #popup-header { +.popup.small .popup-header { padding: 0; } -.popup.small #popup-header { +.popup.small .popup-header { position: relative; border: none; } -.popup.small #popup-title { +.popup.small .popup-title { margin-bottom: 0.6rem; } .popup.small .explanation { margin-bottom: 0.9rem; } -#close-error { - background: var(--accent); +.popup.small .close-error.switch { + background: var(--accent)!important; color: var(--background); } .popup.scrollable { @@ -520,7 +520,7 @@ button:active, font-size: 1.1rem; padding-bottom: var(--padding-1); } -#popup-desc, +.popup-desc, .desc-error, #popup-info-desc { width: 100%; @@ -533,7 +533,7 @@ button:active, .desc-error { padding-bottom: 1.5rem; } -#popup-title { +.popup-title { font-size: 1.5rem; line-height: 1.2em; display: flex; @@ -541,11 +541,11 @@ button:active, margin-bottom: 0.4rem; margin-top: 0.4rem; } -#popup-above-title { +.popup-above-title { color: var(--accent-subtext); font-size: 0.8rem; } -#popup-content { +.popup-content { overflow-x: scroll; overflow-y: auto; height: 100%; @@ -564,7 +564,7 @@ button:active, .bullpadding { padding-left: 0.58rem; } -#popup-header { +.popup-header { position: absolute; z-index: 999; padding-top: calc(env(safe-area-inset-top)/2 + 1.7rem); @@ -646,16 +646,16 @@ button:active, .switch:focus { box-shadow: var(--inset-focus) inset; } -#popup-tabs .switch { +.popup-tabs .switch { background: none; } -.desktop #popup-tabs .switch:hover, -#popup-tabs .switch:active { +.desktop .popup-tabs .switch:hover, +.popup-tabs .switch:active { background: var(--accent-hover-transparent); box-shadow: 0 0 0 0.1rem var(--accent-highlight) inset; } .switch[data-enabled="true"], -#popup-tabs .switch[data-enabled="true"] { +.popup-tabs .switch[data-enabled="true"] { color: var(--background); background: var(--accent)!important; cursor: default; @@ -693,20 +693,20 @@ button:active, padding: var(--gap-no-icon); overflow: clip; } -#back-button { +.back-button { padding: 0; background: none; max-width: 4rem; font-size: 1rem; } -#back-button svg path, +.back-button svg path, .collapse-indicator svg path { fill: var(--accent); } .popup-tab-content[data-enabled="false"] { display: none; } -#popup-tabs { +.popup-tabs { z-index: 999; bottom: 0; position: absolute; @@ -823,7 +823,7 @@ button:active, } .popup-content-inner, .tab-content-settings, -#popup-header-contents { +.popup-header-contents { padding-left: 1rem; padding-right: 1rem; } @@ -947,15 +947,15 @@ button:active, #bottom #paste, #footer .switch, #audioMode, -#popup-content .switches, +.popup-content .switches, .checkbox, .changelog-img, .changelog-banner, -#close-error, +.close-error, .changelog-tag-version, #download-switcher .switch, #popup-about .switch, -#popup-tabs .switch, +.popup-tabs .switch, .text-to-copy, .text-to-copy.text-backdrop, #filename-preview { @@ -965,16 +965,16 @@ button:active, border-radius: 3px / 4px; } .popup, -.scrollable #popup-content { +.scrollable .popup-content { border-radius: 8px; } -#popup-header .glass-bkg { +.popup-header .glass-bkg { border-top-left-radius: 8px 9px; border-top-right-radius: 8px 9px; border-bottom: var(--accent-highlight) solid 0.1rem; top: -1px; } -#popup-tabs .glass-bkg { +.popup-tabs .glass-bkg { border-bottom-left-radius: 8px 9px; border-bottom-right-radius: 8px 9px; border-top: var(--accent-highlight) solid 0.1rem; @@ -1103,12 +1103,12 @@ button:active, padding-top: calc(env(safe-area-inset-bottom)/2 + 1rem); } .popup, - #popup-header .glass-bkg, - #popup-tabs .glass-bkg, + .popup-header .glass-bkg, + .popup-tabs .glass-bkg, .glass-bkg.small { border-radius: 0; } - #popup-tabs .glass-bkg { + .popup-tabs .glass-bkg { bottom: 0; } .switches { @@ -1141,13 +1141,13 @@ button:active, transform: none; transition: transform 210ms cubic-bezier(0.062, 0.82, 0.165, 1), opacity 130ms ease-in-out; } - .popup.small #popup-header { + .popup.small .popup-header { background: none; } .no-animation .popup.small { transition: none; } - #close-error { + .close-error { bottom: 3rem; } #picker-holder::-webkit-scrollbar { @@ -1166,13 +1166,13 @@ button:active, max-height: 100%; box-shadow: none; } - #popup-tabs { + .popup-tabs { padding-bottom: calc(env(safe-area-inset-bottom)/2 + 1.5rem); } .popup-content-inner, .tab-content-settings, .popup-tabs-child, - #popup-header-contents { + .popup-header-contents { padding-left: 0.7rem; padding-right: 0.7rem; } diff --git a/src/front/cobalt.js b/src/front/cobalt.js index 31196215..7da2b8e9 100644 --- a/src/front/cobalt.js +++ b/src/front/cobalt.js @@ -30,6 +30,7 @@ const checkboxes = [ "reduceTransparency", "disableAnimations", "disableMetadata", + "twitterGif", ]; const exceptions = { // used for mobile devices "vQuality": "720" @@ -235,7 +236,7 @@ function popup(type, action, text) { `` + - `` + + `` + `` } break; @@ -252,7 +253,7 @@ function popup(type, action, text) { }>` + `
${text.arr[i].type}
` + `
` + - `` + + `` + `` } eid("picker-download").classList.remove("visible"); @@ -381,6 +382,7 @@ async function download(url) { } if (sGet("disableMetadata") === "true") req.disableMetadata = true; + if (sGet("twitterGif") === "true") req.twitterGif = true; let j = await fetch(`${apiURL}/api/json`, { method: "POST", @@ -601,9 +603,9 @@ window.onload = () => { if (setUn !== null) { if (setUn) { sSet("migrated", "true") - eid("desc-migration").innerHTML += `

${loc.DataTransferSuccess}` + eid("desc-migration").innerHTML += `

${loc.DataTransferSuccess}` } else { - eid("desc-migration").innerHTML += `

${loc.DataTransferError}` + eid("desc-migration").innerHTML += `

${loc.DataTransferError}` } } } @@ -614,6 +616,11 @@ window.onload = () => { window.history.replaceState(null, '', window.location.pathname); notificationCheck(); + + // fix for animations not working in Safari + if (isIOS) { + document.addEventListener('touchstart', () => {}, true); + } } eid("url-input-area").addEventListener("keydown", (e) => { button(); diff --git a/src/front/updateBanners/shutup.png b/src/front/updateBanners/shutup.png deleted file mode 100644 index cbc80ae8..00000000 Binary files a/src/front/updateBanners/shutup.png and /dev/null differ diff --git a/src/front/updateBanners/shutup.webp b/src/front/updateBanners/shutup.webp new file mode 100644 index 00000000..e0a08a7d Binary files /dev/null and b/src/front/updateBanners/shutup.webp differ diff --git a/src/localization/languages/en.json b/src/localization/languages/en.json index 70161ef0..9a1e591f 100644 --- a/src/localization/languages/en.json +++ b/src/localization/languages/en.json @@ -8,7 +8,7 @@ "LinkInput": "paste the link here", "AboutSummary": "cobalt is your go-to place for downloads from social and media platforms. zero ads, trackers, or other creepy bullshit. simply paste a share link and you're ready to rock!", "EmbedBriefDescription": "save what you love. no ads, trackers, or other creepy bullshit.", - "MadeWithLove": "made with <3 by wukko", + "MadeWithLove": "made with <3 by wukko", "AccessibilityInputArea": "link input area", "AccessibilityOpenAbout": "open about popup", "AccessibilityDownloadButton": "download button", @@ -117,7 +117,6 @@ "ShareURL": "share", "ErrorTweetUnavailable": "couldn't find anything about this tweet. this could be because its visibility is limited. try another one!", "ErrorTwitterRIP": "twitter has restricted access to any content to unauthenticated users. while there's a way to get regular tweets, spaces are, unfortunately, impossible to get at this time. i am looking into possible solutions.", - "UrgentDonate": "cobalt needs your help!", "PopupCloseDone": "done", "Accessibility": "accessibility", "SettingsReduceTransparency": "reduce transparency", @@ -134,10 +133,7 @@ "KeyboardShortcutClosePopup": "close all popups", "CollapseLegal": "terms and ethics", "FairUse": "cobalt is a web tool that makes it easier to download content from the internet and takes zero liability. processing servers work like limited proxies, so no media content is ever cached or stored.\n\nyou (end user) are responsible for what you download, how you use and distribute that content. please be mindful when using content of others and always credit original creators.\n\nwhen used in education purposes (lecture, homework, etc) please attach the source link.\n\nfair use and credits benefit everyone.", - "UrgentFeatureUpdate71": "more supported services!", - "UrgentThanks": "thank you for support!", "SettingsDisableMetadata": "don't add metadata", - "UrgentNewDomain": "new domain, same cobalt", "NewDomainWelcomeTitle": "hey there!", "NewDomainWelcome": "cobalt is moving! same features, same owner, simply a more rememberable domain. and still no ads.\n\ncobalt.tools is the new main domain, aka where you are now. make sure to update your bookmarks and reinstall the web app!", "DataTransferSuccess": "btw, your settings have been transferred automatically :)", @@ -154,10 +150,12 @@ "FilenamePreviewVideoTitle": "Video Title", "FilenamePreviewAudioTitle": "Audio Title", "FilenamePreviewAudioAuthor": "Audio Author", - "UrgentFilenameUpdate": "customizable file names!", - "UrgentTwitterPatch": "fixes and easier downloads", "StatusPage": "service status page", "TroubleshootingGuide": "self-troubleshooting guide", - "UpdateNewYears": "new years clean up" + "DonateImageDescription": "cat sleeping on a laptop keyboard and typing letters repeatedly", + "UpdateNewYears": "new years clean up", + "SettingsTwitterGif": "convert gifs to .gif", + "SettingsTwitterGifDescription": "converting looping videos to .gif reduces quality and majorly increases file size. if you want best efficiency, keep this setting off.", + "UpdateTwitterGif": "twitter gifs and pinterest" } } diff --git a/src/localization/languages/ru.json b/src/localization/languages/ru.json index df3ae5a6..cae12454 100644 --- a/src/localization/languages/ru.json +++ b/src/localization/languages/ru.json @@ -8,7 +8,7 @@ "LinkInput": "вставь ссылку сюда", "AboutSummary": "кобальт - твой друг при скачивании контента из соцсетей и других сервисов. никакой рекламы, трекеров и прочего мусора. вставляешь ссылку и получаешь файл. всё. ничего лишнего.", "EmbedBriefDescription": "сохраняй то, что любишь. без рекламы, трекеров и лишней мороки.", - "MadeWithLove": "сделано с любовью <3", + "MadeWithLove": "сделано с любовью <3", "AccessibilityInputArea": "зона вставки ссылки", "AccessibilityOpenAbout": "открыть окно с инфой", "AccessibilityDownloadButton": "кнопка скачивания", @@ -118,7 +118,6 @@ "ShareURL": "поделиться", "ErrorTweetUnavailable": "не смог найти что-либо об этом твите. возможно его видимость была ограничена. попробуй другой!", "ErrorTwitterRIP": "твиттер ограничил доступ к любому контенту на сайте для пользователей без аккаунтов. я нашёл лазейку, чтобы доставать обычные твиты, а для spaces, к сожалению, нет. я ищу возможные варианты выхода из ситуации.", - "UrgentDonate": "нужна твоя помощь!", "PopupCloseDone": "готово", "Accessibility": "общедоступность", "SettingsReduceTransparency": "уменьшить прозрачность", @@ -135,10 +134,7 @@ "KeyboardShortcutClosePopup": "закрыть все окна", "CollapseLegal": "принципы и этика", "FairUse": "кобальт - это веб инструмент для облегчения скачивания контента из интернета. сервера обработки работают как ограниченные прокси, так что ничего никогда не сохраняется или кэшируется.\n\nкобальт не несёт никакой ответственности, только ты (конечный пользователь) несёшь ответственность за то, что скачиваешь, как используешь и распространяешь скачанный контент. будь сознателен при использовании чужого контента и всегда указывай авторов!\n\nприкладывай ссылку на источник при использовании в образовательных целях (лекции, домашние задания и т.п.)\n\nчестное использование и указание авторства выгодно всем.", - "UrgentFeatureUpdate71": "расширение поддержки сервисов!", - "UrgentThanks": "спасибо за поддержку!", "SettingsDisableMetadata": "не добавлять метаданные", - "UrgentNewDomain": "новый домен, тот же кобальт", "NewDomainWelcomeTitle": "привет!", "NewDomainWelcome": "кобальт переезжает! те же функции, тот же владелец, просто более запоминающийся домен. по-прежнему без рекламы.\n\ncobalt.tools - новый основной домен, т.е. где ты сейчас находишься. не забудь обновить закладки и переустановить веб-приложение!", "DataTransferSuccess": "кстати, твои настройки были перенесены автоматически :)", @@ -156,10 +152,12 @@ "FilenamePreviewVideoTitle": "Название Видео", "FilenamePreviewAudioTitle": "Название Аудио", "FilenamePreviewAudioAuthor": "Автор Аудио", - "UrgentFilenameUpdate": "изменяемые названия файлов!", - "UrgentTwitterPatch": "фиксы и удобное скачивание", "StatusPage": "статус серверов", "TroubleshootingGuide": "гайд по устранению проблем", - "UpdateNewYears": "новогодняя уборка" + "DonateImageDescription": "кошка спит на клавиатуре ноутбука и многократно печатает буквы", + "UpdateNewYears": "новогодняя уборка", + "SettingsTwitterGif": "конвертировать гифки в .gif", + "SettingsTwitterGifDescription": "конвертирование зацикленного видео в .gif снижает качество и значительно увеличивает размер файла. если важна максимальная эффективность, то не используй эту функцию.", + "UpdateTwitterGif": "гифки с твиттера и одноклассники" } } diff --git a/src/localization/manager.js b/src/localization/manager.js index ce396891..2b251fe3 100644 --- a/src/localization/manager.js +++ b/src/localization/manager.js @@ -17,7 +17,7 @@ export async function loadLoc() { export function replaceBase(s) { return s - .replace(/\n/g, '
') + .replace(/\n/g, '
') .replace(/{saveToGalleryShortcut}/g, links.saveToGalleryShortcut) .replace(/{repo}/g, repo) .replace(/{statusPage}/g, links.statusPage) diff --git a/src/modules/changelog/changelog.json b/src/modules/changelog/changelog.json index 26092370..0794fafb 100644 --- a/src/modules/changelog/changelog.json +++ b/src/modules/changelog/changelog.json @@ -5,6 +5,7 @@ "title": "new years clean up! bug fixes and fresh look for the home page", "banner": { "file": "catroomba.webp", + "alt": "a cat riding a roomba vacuum", "width": 300, "height": 168 }, @@ -16,6 +17,7 @@ "title": "bugfixes and better downloads!", "banner": { "file": "meowthpolishegg.webp", + "alt": "meowth polishing a togepi egg", "width": 640, "height": 480 }, @@ -26,6 +28,7 @@ "title": "customizable file names, instagram stories, and first cobalt sponsor!", "banner": { "file": "meowthcenter.webp", + "alt": "meowth plush in a datacenter wearing a hardhat, wielding a hammer", "width": 851, "height": 640 }, @@ -36,6 +39,7 @@ "title": "support for twitch clips and rutube!", "banner": { "file": "twitchupdate.webp", + "alt": "meowth plush staring into the camera, laptop with generic purple service in the background", "width": 851, "height": 640 }, @@ -46,6 +50,7 @@ "title": "new domain, what's coming in future, bug fixes, and more!", "banner": { "file": "newdomain.webp", + "alt": "text: new domain, same cobalt", "width": 960, "height": 540 }, @@ -56,6 +61,7 @@ "title": "extended video length limit, metadata toggle, ui improvements, and more!", "banner": { "file": "meowthsnap.webp", + "alt": "cartoon meowth pointing paw dramatically and saying something", "width": 500, "height": 280 }, @@ -66,6 +72,7 @@ "title": "instagram, streamable, video metadata, and more!", "banner": { "file": "meowthproductions.webp", + "alt": "meowth roaring in a fancy circle, à la MGM studios intro", "width": 640, "height": 358 }, @@ -76,6 +83,7 @@ "title": "biggest ui refresh yet!", "banner": { "file": "meowthcooking.webp", + "alt": "meowth handling orders in a restaurant", "width": 640, "height": 360 }, @@ -86,6 +94,7 @@ "title": "all network issues have been fixed!", "banner": { "file": "meowthhammer.webp", + "alt": "meowth plush holding a hammer in real life", "width": 1280, "height": 827 }, @@ -96,6 +105,7 @@ "title": "better reliability, new infrastructure, pinterest support, and way more!", "banner": { "file": "catswitchboxes.webp", + "alt": "a cat climbing into two empty boxes of asahi beer", "width": 600, "height": 314 }, @@ -105,6 +115,7 @@ "title": "instagram support, docker, and more!", "banner": { "file": "catphonestand.webp", + "alt": "a cat holding a phone under its chin while a person plays clash of clans on it", "width": 451, "height": 272 }, @@ -114,6 +125,7 @@ "title": "better looks, better feel", "banner": { "file": "cattired.webp", + "alt": "a cat laying on a sofa face down, wiggling its tail", "width": 640, "height": 286 }, @@ -123,6 +135,7 @@ "title": "fastest one in the game", "banner": { "file": "catspeed.webp", + "alt": "a cat running very fast in an exercise wheel", "width": 640, "height": 356 }, @@ -132,6 +145,7 @@ "title": "the evil has been defeated", "banner": { "file": "happymeowth.webp", + "alt": "meowth jumping up into the sky very excitedly", "width": 500, "height": 330 }, @@ -141,6 +155,7 @@ "title": "it's all about attention to detail!", "banner": { "file": "valentines.webp", + "alt": "relaxed meowth with sakura petals falling in front of them", "width": 489, "height": 374 }, @@ -150,6 +165,7 @@ "title": "prettier than ever", "banner": { "file": "catmakeup.webp", + "alt": "a cat being brushed with a powder makeup brush", "width": 394, "height": 266 }, @@ -159,6 +175,7 @@ "title": "we're better together! thank you for bug reports.", "banner": { "file": "bettertogether.webp", + "alt": "various different pokémon jumping in happiness", "width": 640, "height": 358 }, @@ -168,6 +185,7 @@ "title": "mute videos and proper soundcloud support", "banner": { "file": "shutup.webp", + "alt": "a cat yawning, with a crossed out loudspeaker icon next to it", "width": 1024, "height": 665 }, @@ -177,6 +195,7 @@ "title": "better, faster, stronger, stable", "banner": { "file": "meowthstrong.webp", + "alt": "meowth stretching", "width": 500, "height": 280 }, @@ -186,6 +205,7 @@ "title": "over 1 million monthly requests. thank you.", "banner": { "file": "onemillionr.webp", + "alt": "cobalt logo and a confetti emoji", "width": 1441, "height": 1441 }, @@ -199,6 +219,7 @@ "title": "developers, developers, developers, developers", "banner": { "file": "developers.webp", + "alt": "steve ballmer going \"developers, developers, developers\"", "width": 640, "height": 360 }, diff --git a/src/modules/changelog/changelogManager.js b/src/modules/changelog/changelogManager.js index b267b321..b8763fb5 100644 --- a/src/modules/changelog/changelogManager.js +++ b/src/modules/changelog/changelogManager.js @@ -5,33 +5,35 @@ let changelog = loadJSON('./src/modules/changelog/changelog.json') export default function(string) { try { + const currentChangelog = changelog.current; + switch (string) { case "version": - return `v.${changelog["current"]["version"]}${ - changelog["current"]["date"] ? `· ${changelog["current"]["date"]}` : '' + return `v.${currentChangelog.version}${ + currentChangelog.date ? `· ${currentChangelog.date}` : '' }` case "title": - return replaceBase(changelog["current"]["title"]); + return replaceBase(currentChangelog.title); case "banner": - return changelog["current"]["banner"] ? { - url: `updateBanners/${changelog["current"]["banner"]["file"]}`, - width: changelog["current"]["banner"]["width"], - height: changelog["current"]["banner"]["height"] + const currentBanner = changelog.current.banner; + return currentBanner ? { + ...currentBanner, + url: `updateBanners/${currentBanner.file}` } : false; case "content": - return replaceBase(changelog["current"]["content"]); + return replaceBase(currentChangelog.content); case "history": - return changelog["history"].map((i) => { + return changelog.history.map((log) => { + const banner = log.banner; return { - title: replaceBase(i["title"]), - version: `v.${i["version"]}${ - i["date"] ? `· ${i["date"]}` : '' + title: replaceBase(log.title), + version: `v.${log.version}${ + log.date ? `· ${log.date}` : '' }`, - content: replaceBase(i["content"]), - banner: i["banner"] ? { - url: `updateBanners/${i["banner"]["file"]}`, - width: i["banner"]["width"], - height: i["banner"]["height"] + content: replaceBase(log.content), + banner: banner ? { + ...banner, + url: `updateBanners/${banner.file}` } : false, } }); diff --git a/src/modules/emoji.js b/src/modules/emoji.js index f2bab1b9..f4793cb5 100644 --- a/src/modules/emoji.js +++ b/src/modules/emoji.js @@ -62,5 +62,5 @@ export default function(emoji, size, disablePadding, fluent) { let filePath = `emoji/${names[emoji]}.svg`; if (fluent) filePath = `emoji/3d/${names[emoji]}.svg`; - return `` + return `` } diff --git a/src/modules/pageRender/elements.js b/src/modules/pageRender/elements.js index 308f9748..a677d2bc 100644 --- a/src/modules/pageRender/elements.js +++ b/src/modules/pageRender/elements.js @@ -59,27 +59,27 @@ export function popup(obj) { body = `` for (let i = 0; i < obj.body.length; i++) { if (obj.body[i]["text"].length > 0) { - classes = obj.body[i]["classes"] ? obj.body[i]["classes"] : [] + classes = obj.body[i]["classes"] ?? [] if (i !== obj.body.length - 1 && !obj.body[i]["nopadding"]) { classes.push("desc-padding") } - body += obj.body[i]["raw"] ? obj.body[i]["text"] : `` + body += obj.body[i]["raw"] ? obj.body[i]["text"] : `
${obj.body[i]["text"]}
` } } } return ` ${obj.standalone ? `