diff --git a/CNAME b/CNAME index 7453451..070df1b 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -octogram.me +octogram.me \ No newline at end of file diff --git a/assets/src/octogram.home.js b/assets/src/octogram.home.js index 5f7458a..55f7c4e 100644 --- a/assets/src/octogram.home.js +++ b/assets/src/octogram.home.js @@ -1,6 +1,6 @@ -import {calculateSize, clearPage, fixInjectionTags, generateWaveGradient} from "./octogram.utils.js"; +import { calculateSize, clearPage, fixInjectionTags, generateWaveGradient } from "./octogram.utils.js"; import * as header from "./octogram.header.js"; -import {getStringRef} from "./octogram.translations.js"; +import { getStringRef } from "./octogram.translations.js"; import * as footer from "./octogram.footer.js"; import * as changelog from "./octogram.changelog.js"; import * as privacyPolicy from "./octogram.privacy.js"; @@ -38,19 +38,19 @@ function init() { pageContainer.appendChild(footer.createElement()); document.body.appendChild(pageContainer); - + loadVersions(); - + if (!particlesWorker) { particlesWorker = new Worker('/assets/lib/particles-worker.js', { type: 'module' }); } - + window.addEventListener('resize', onResize); - + const canvasBoundingRect = particlesCanvas.getBoundingClientRect(); particlesCanvas.width = canvasBoundingRect.width; particlesCanvas.height = canvasBoundingRect.height; - + const offscreen = particlesCanvas.transferControlToOffscreen(); particlesWorker.postMessage({ canvas: offscreen }, [offscreen]); } @@ -74,7 +74,7 @@ function onResize() { } particlesWorker.postMessage({ canvas: false }); - + particlesOnResizeTimeout = setTimeout(() => { const canvasBoundingRect = particlesCanvas.getBoundingClientRect(); particlesWorker.postMessage({ resize: true, width: canvasBoundingRect.width, height: canvasBoundingRect.height }); @@ -157,22 +157,22 @@ function generateAiFeatures() { messageTitle.classList.add('title'); messageTitle.textContent = getStringRef('AI_TITLE'); messageTitle.appendChild(lampIcon); - + const featuresList = document.createElement('div'); featuresList.classList.add('features-list'); featuresList.appendChild(createFeature(getStringRef('AI_FEAT_1'), getStringRef('AI_FEAT_1_DESC'), 'ManyProvidersFeat1.png')); featuresList.appendChild(createFeature(getStringRef('AI_FEAT_2'), getStringRef('AI_FEAT_2_DESC'), 'ChatContextFeat2.png')); featuresList.appendChild(createFeature(getStringRef('AI_FEAT_3'), getStringRef('AI_FEAT_3_DESC'), 'CustomModelsFeat3.png', true)); - + const featuresContainer = document.createElement('div'); featuresContainer.classList.add('features-container'); featuresContainer.appendChild(messageTitle); featuresContainer.appendChild(featuresList); - + const features = document.createElement('div'); features.classList.add('features'); features.appendChild(featuresContainer); - + return features; } @@ -180,39 +180,51 @@ function createFeature(title, description, image, fromBottom = false) { const featureTitle = document.createElement('div'); featureTitle.classList.add('feature-title'); featureTitle.textContent = title; - + const featureDescription = document.createElement('div'); featureDescription.classList.add('feature-description'); featureDescription.textContent = description; - + + const textWrapper = document.createElement('div'); + textWrapper.classList.add('feature-text'); + textWrapper.appendChild(featureTitle); + textWrapper.appendChild(featureDescription); + const shadow = document.createElement('div'); shadow.classList.add('shadow'); const realImage = document.createElement('img'); realImage.classList.add('real-image'); - realImage.src = '/assets/images/'+image; + realImage.src = '/assets/images/' + image; const deviceFrame = document.createElement('img'); deviceFrame.classList.add('frame'); deviceFrame.src = '/assets/images/DeviceFrameTelegram.Android.svg'; + const featureImage = document.createElement('div'); featureImage.classList.add('feature-image'); featureImage.appendChild(shadow); featureImage.appendChild(realImage); featureImage.appendChild(deviceFrame); - + const feature = document.createElement('div'); feature.classList.add('feature'); feature.classList.toggle('from-bottom', fromBottom); - feature.appendChild(featureTitle); - feature.appendChild(featureDescription); - feature.appendChild(featureImage); - + + if (fromBottom) { + feature.appendChild(featureImage); + feature.appendChild(textWrapper); + } else { + feature.appendChild(textWrapper); + feature.appendChild(featureImage); + } + return feature; } + function generateFeatures() { const background = document.createElement('div'); background.classList.add('background'); - + const leftPartSticker = document.createElement('lottie-player'); leftPartSticker.toggleAttribute('autoplay'); leftPartSticker.toggleAttribute('loop'); @@ -224,28 +236,28 @@ function generateFeatures() { leftPart.classList.add('left-part'); leftPart.appendChild(leftPartSticker); leftPart.appendChild(leftPartTitle); - + const rightPart = document.createElement('div'); rightPart.classList.add('right-part'); rightPart.appendChild(createDeviceWithMockup('AppearanceGen1.png')); rightPart.appendChild(createDeviceWithMockup('AppearanceGen2.png')); rightPart.appendChild(createDeviceWithMockup('AppearanceGen3.png')); - + const featuresContent = document.createElement('div'); featuresContent.classList.add('content'); featuresContent.appendChild(leftPart); featuresContent.appendChild(rightPart); - + const upperWaves = document.createElement('div'); upperWaves.classList.add('waves'); initBackground(upperWaves); - + const features = document.createElement('div'); features.classList.add('features-standard'); features.appendChild(background); features.appendChild(featuresContent); features.appendChild(upperWaves); - + return features; } @@ -254,7 +266,7 @@ function createDeviceWithMockup(image) { shadow.classList.add('shadow'); const realImage = document.createElement('img'); realImage.classList.add('real-image'); - realImage.src = '/assets/images/'+image; + realImage.src = '/assets/images/' + image; const featureImage = document.createElement('div'); featureImage.classList.add('device-image'); featureImage.appendChild(shadow); @@ -294,7 +306,7 @@ function generateDownload() { const separator = document.createElement('div'); separator.classList.add('separator'); - separator.style.setProperty('--text', '"'+getStringRef('DOWNLOAD_OR')+'"'); + separator.style.setProperty('--text', '"' + getStringRef('DOWNLOAD_OR') + '"'); const stores = document.createElement('div'); stores.classList.add('stores'); @@ -335,11 +347,11 @@ function appendStores(stores) { } function generateStore({ - iconUrl, - id, - href, - isUnavailable = false - }) { + iconUrl, + id, + href, + isUnavailable = false +}) { const storeIconElement = document.createElement('img'); storeIconElement.src = iconUrl; const storeIconContainer = document.createElement('div'); @@ -389,7 +401,7 @@ function loadVersions() { loadVersionsWithResponse(precachedResponse); } else { const XML = new XMLHttpRequest(); - XML.open('GET', 'https://api.github.com/repos/OctoGramApp/OctoGram/releases?cache='+Math.random().toString(), true); + XML.open('GET', 'https://api.github.com/repos/OctoGramApp/OctoGram/releases?cache=' + Math.random().toString(), true); XML.send(); XML.addEventListener('readystatechange', (e) => { if (e.target.readyState === 4 && e.target.status === 200) { @@ -407,7 +419,7 @@ function loadVersions() { function loadVersionsWithResponse(response) { let selectedRelease = response[0]; if (selectedRelease['prerelease']) { - for(const release of response) { + for (const release of response) { if (!release['prerelease']) { selectedRelease = release; break; @@ -416,7 +428,7 @@ function loadVersionsWithResponse(response) { } let sizeSum = 0; - for(const asset of selectedRelease['assets']) { + for (const asset of selectedRelease['assets']) { sizeSum += asset['size']; } sizeSum /= selectedRelease['assets'].length; diff --git a/assets/src/octogram.translations.js b/assets/src/octogram.translations.js index aef3f21..1f2c7d6 100644 --- a/assets/src/octogram.translations.js +++ b/assets/src/octogram.translations.js @@ -64,7 +64,7 @@ const TRANSLATIONS_REF = { CHANGELOG_DOWNLOAD_SUBTITLE_SUGGESTION: 'The {0} version should be the most suitable and stable one for your device.', CHANGELOG_DOWNLOAD_SELECT: 'Select your option', CHANGELOG_DOWNLOAD_BUTTON: 'Download', - + AI_TITLE: 'Now with AI', AI_FEAT_1: 'So many providers. Total freedom.', AI_FEAT_1_DESC: 'Access the power of Gemini, ChatGPT, and OpenRouter — all in one place, ready when you need them most.', @@ -72,7 +72,7 @@ const TRANSLATIONS_REF = { AI_FEAT_2_DESC: 'Automatically use past messages to boost replies. Use Ask on Media to get instant insights from photos, videos, and more.', AI_FEAT_3: 'Create your own AI. Unlimited possibilities.', AI_FEAT_3_DESC: 'Design fully customizable models with your own prompts. Tailor OctoGram AI to your unique style and needs.', - + FT_T: 'All the\ncustomizations\nyou like.', DOWNLOAD_TITLE: 'The experience begins', @@ -118,17 +118,17 @@ function getStringRef(name, ...args) { if (args.length) { const isSortObject = args.some((e) => typeof e == 'object'); - if(isSortObject){ + if (isSortObject) { const splittedString = string.split('{'); let temporaryString = ''; - for(const part of splittedString){ - if(part[1] === '}' && !isNaN(parseInt(part[0]))){ + for (const part of splittedString) { + if (part[1] === '}' && !isNaN(parseInt(part[0]))) { const isElement = args[part[0]] instanceof HTMLElement; - const repartSet = ''; + const repartSet = ''; temporaryString += isElement && repartSet || args[part[0]]; temporaryString += part.slice(2); - }else{ + } else { temporaryString += part; } } @@ -136,16 +136,16 @@ function getStringRef(name, ...args) { const newGeneratedElement = document.createElement('span'); newGeneratedElement.classList.add('dynamic-translation'); newGeneratedElement.innerHTML = temporaryString; - for(const element of newGeneratedElement.childNodes){ - if(element.tagName === 'SMALI' && element.dataset.id){ + for (const element of newGeneratedElement.childNodes) { + if (element.tagName === 'SMALI' && element.dataset.id) { element.replaceWith(args[element.dataset.id]); } } return newGeneratedElement; - }else{ - for(const [id, arg] of args.entries()){ - string = string.replaceAll('{'+id+'}', arg); + } else { + for (const [id, arg] of args.entries()) { + string = string.replaceAll('{' + id + '}', arg); } } } @@ -168,7 +168,7 @@ function getTextNodeByStringRef(name, ...args) { function getLanguageCode() { if (typeof window.navigator.language != 'undefined') { - for(const lang of window.navigator.language.split('-')) { + for (const lang of window.navigator.language.split('-')) { if (AVAILABLE_LANGUAGES.includes(lang.toLowerCase())) { if (lang.toLowerCase() === 'es') { return 'es-ES'; diff --git a/assets/styles/elements/octogram.aifeatures.css b/assets/styles/elements/octogram.aifeatures.css index 52faea7..4ea55f0 100644 --- a/assets/styles/elements/octogram.aifeatures.css +++ b/assets/styles/elements/octogram.aifeatures.css @@ -1,16 +1,16 @@ -body > .page > .features { +body>.page>.features { width: 100%; display: flex; justify-content: center; margin-bottom: 60px; } -body > .page > .features .features-container { +body>.page>.features .features-container { width: min(95vw, 1200px); max-width: min(95vw, 1200px); } -body > .page > .features .features-container .title { +body>.page>.features .features-container .title { color: #FFFFFF; font-size: 2.3em; font-weight: 600; @@ -20,12 +20,12 @@ body > .page > .features .features-container .title { gap: 15px; } -body > .page > .features .features-container .title lottie-player { +body>.page>.features .features-container .title lottie-player { width: 30px; height: 30px; } -body > .page > .features .features-container .features-list { +body>.page>.features .features-container .features-list { display: flex; align-items: center; justify-content: center; @@ -33,94 +33,94 @@ body > .page > .features .features-container .features-list { } @media screen and (max-width: 900px) { - body > .page > .features .features-container .features-list { + body>.page>.features .features-container .features-list { flex-direction: column; } } -body > .page > .features .features-container .features-list .feature { +body>.page>.features .features-container .features-list .feature { flex: 1; background: #12062a; min-height: 700px; padding: 30px; + padding-bottom: 0; border-radius: 15px; box-sizing: border-box; position: relative; overflow: hidden; + display: flex; + flex-direction: column; + justify-content: space-between; } @media screen and (max-width: 1200px) and (min-width: 900px) { - body > .page > .features .features-container .features-list .feature { + body>.page>.features .features-container .features-list .feature { min-height: 650px; } } @media screen and (max-width: 600px) { - body > .page > .features .features-container .features-list .feature { + body>.page>.features .features-container .features-list .feature { min-height: 550px; } } @media screen and (max-width: 900px) and (min-width: 600px) { - body > .page > .features .features-container .features-list .feature { + body>.page>.features .features-container .features-list .feature { max-width: 500px; } } -body > .page > .features .features-container .features-list .feature.from-bottom { - display: flex; - justify-content: flex-end; - flex-direction: column; +body>.page>.features .features-container .features-list .feature.from-bottom { + padding: 30px; + padding-top: 0; + gap: 30px; } -body > .page > .features .features-container .features-list .feature .feature-title { +body>.page>.features .features-container .features-list .feature .feature-title { color: #695bf5; font-size: 1.5em; font-weight: 600; } -body > .page > .features .features-container .features-list .feature .feature-description { +body>.page>.features .features-container .features-list .feature .feature-description { margin-top: 15px; color: rgba(255, 255, 255, 0.8); font-size: 1.2em; line-height: 25px; } -body > .page > .features .features-container .features-list .feature .feature-image { - position: absolute; +body>.page>.features .features-container .features-list .feature .feature-image { + position: relative; left: 50%; transform: translateX(-50%); - width: 70%; + width: 80%; +} + +body>.page>.features .features-container .features-list .feature.feature.from-bottom .feature-image { + transform: translate(-50%, -5%); } @media screen and (max-width: 900px) and (min-width: 600px) { - body > .page > .features .features-container .features-list .feature .feature-image { + body>.page>.features .features-container .features-list .feature .feature-image { width: 300px; } } @media screen and (max-width: 600px) { - body > .page > .features .features-container .features-list .feature .feature-image { + body>.page>.features .features-container .features-list .feature .feature-image { width: 220px; } } @media screen and (max-width: 700px) { - body > .page > .features .features-container .features-list .feature:not(.from-bottom) .feature-image { + body>.page>.features .features-container .features-list .feature:not(.from-bottom) .feature-image { position: relative; transform: translateX(-50%) translateY(15%); } } -body > .page > .features .features-container .features-list .feature:not(.from-bottom) .feature-image { - bottom: 0; -} - -body > .page > .features .features-container .features-list .feature.from-bottom .feature-image { - top: 0; -} - -body > .page > .features .features-container .features-list .feature .feature-image .shadow { +body>.page>.features .features-container .features-list .feature .feature-image .shadow { position: absolute; height: 50%; background: linear-gradient(90deg, rgba(0, 0, 0, 0.4), transparent); @@ -129,11 +129,11 @@ body > .page > .features .features-container .features-list .feature .feature-im z-index: -1; } -body > .page > .features .features-container .features-list .feature.from-bottom .feature-image .shadow { +body>.page>.features .features-container .features-list .feature.from-bottom .feature-image .shadow { display: none; } -body > .page > .features .features-container .features-list .feature .feature-image .real-image { +body>.page>.features .features-container .features-list .feature .feature-image .real-image { --init: 4%; margin-left: var(--init); width: calc(100% - var(--init) * 2); @@ -141,28 +141,28 @@ body > .page > .features .features-container .features-list .feature .feature-im box-shadow: 0 0 42px 9px black; } -body > .page > .features .features-container .features-list .feature:not(.from-bottom) .feature-image .real-image { +body>.page>.features .features-container .features-list .feature:not(.from-bottom) .feature-image .real-image { border-top-left-radius: 20px; border-top-right-radius: 20px; margin-top: var(--init); } -body > .page > .features .features-container .features-list .feature.from-bottom .feature-image .real-image { +body>.page>.features .features-container .features-list .feature.from-bottom .feature-image .real-image { border-bottom-left-radius: 20px; border-bottom-right-radius: 20px; margin-bottom: var(--init); } -body > .page > .features .features-container .features-list .feature .feature-image .frame { +body>.page>.features .features-container .features-list .feature .feature-image .frame { position: absolute; left: 0; width: 100%; } -body > .page > .features .features-container .features-list .feature:not(.from-bottom) .feature-image .frame { +body>.page>.features .features-container .features-list .feature:not(.from-bottom) .feature-image .frame { top: 0; } -body > .page > .features .features-container .features-list .feature.from-bottom .feature-image .frame { +body>.page>.features .features-container .features-list .feature.from-bottom .feature-image .frame { bottom: 0; } \ No newline at end of file