PageSourceSearch

https://kapar.org/js/app.js

js kapar.org collected 2026-10-02 02:04:09 UTC 19,652 bytes, 408 lines download raw bytes

1// Applications Data Array
2const appsData = [
3    {
4        id: "dava-belgelerim",
5        title: "Dava Belgelerim",
6        category: "legal",
7        featured: true, // Asymmetric display (two columns)
8        badge: "Tüm Platformlar (Mobil & Masaüstü)",
9        icon: "fa-solid fa-scale-balanced",
10        image: "assets/dava_belgelerim_logo.png",
11        description: "UYAP formatındaki (.udf) resmi dava dosyalarını mobil cihazlarınızda ve bilgisayarınızda anında görüntüleyin. Belgeleri PDF, DOC veya TXT formatlarına dönüştürün, toplu işlem yapın ve güvenle paylaşın.",
12        specs: [
13            "Gelişmiş .udf XML Ayrıştırıcı & Çevrimdışı Görüntüleyici",
14            "Karanlık & Kalitesiz TIFF Taramaları Netleştirme Algoritması",
15            "Klasör Yapısını Koruyan Akıllı Toplu PDF Dönüştürücü",
16            "Cihaz İçi Tam Arama (İnternet/Bulut Bağlantısı Gerekmez)"
17        ],
18        tags: ["Flutter", "Dart", "UDF Parser", "TIFF to PDF", "Toplu Dönüştürücü", "Windows & Linux & Android & iOS"],
19        primaryLink: "dava-belgelerim.html",
20        primaryLabel: "Detaylar",
21        secondaryLink: "https://play.google.com/store/apps/details?id=com.aka.uyap_okuyucu",
22        secondaryLabel: "Google Play",
23        privacyLink: "dava-belgelerim-gizlilik-politikasi.html"
24    },
25    {
26        id: "sozgec",
27        title: "Sözgeç",
28        category: "productivity",
29        featured: true, // Double column display
30        badge: "Mobil Uygulama ve Chrome Eklentisi",
31        icon: "fa-solid fa-filter-circle-xmark",
32        image: "assets/sozgec_logo.png",
33        description: "Ekşi Sözlük için topluluk tabanlı ve yapay zeka destekli akıllı moderasyon mobil uygulaması ve Chrome eklentisi. Kutsal bilgi kaynağındaki troll kirliliğini, provokasyonları, fanatizmi ve nefret söylemini topluluğun ve yapay zekanın gücüyle hem telefonunuzda hem de tarayıcınızda süzün.",
34        specs: [
35            "Troll Skoru Rozetleri & Detaylı Kategori Analizi",
36            "Otomatik İçerik Gizleme & Tek Tıkla Orijinal Entry Gösterimi",
37            "Kişiselleştirilebilir Duyarlılık ve Hassasiyet Ayarı",
38            "Tek Tıkla Kolay Raporlama ve Bireysel Engelleme (🚫)",
39            "Mobil Uygulamada Kanser Başlık Engelleme & Temiz Gündem Listeleri",
40            "Işık Hızında Engelleme & Taptaze Güncel Liste Senkronizasyonu"
41        ],
42        tags: ["Chrome Eklentisi", "Android Uygulaması", "Ekşi Sözlük", "Yapay Zeka", "Topluluk Filtresi"],
43        primaryLink: "sozgec.html",
44        primaryLabel: "Detaylar & Kullanım",
45        secondaryLink: "https://chromewebstore.google.com/detail/s%C3%B6zge%C3%A7-ek%C5%9Fi-s%C3%B6zl%C3%BCk-modera/imdmglklbkggpncfibeibbeopecomdkk?authuser=0&hl=en",
46        secondaryLabel: "Chrome Mağazası",
47        privacyLink: "sozgec-gizlilik-politikasi.html"
48    },
49    {
50        id: "gazelist",
51        title: "GAZELIST",
52        category: "productivity",
53        featured: true, // Double column display
54        badge: "All Platforms (Mobile & Desktop)",
55        icon: "fa-solid fa-list-check",
56        image: "assets/gazelist_logo.png",
57        description: "A secure, hierarchical task manager and Pomodoro timer. Nest subtasks to any depth, track focus time, sync automatically with Google Drive, and analyze your productivity history with absolute privacy.",
58        specs: [
59            "Unlimited Nested Task Hierarchy & Drag-and-Drop",
60            "Task-Bound Focus Timer with Ambient Notification Chimes",
61            "Dynamic Tagging (#tag/@person) with Autocomplete Overlays",
62            "Preserved Activity History & Google Drive Automatic Sync"
63        ],
64        tags: ["Flutter", "Dart", "Pomodoro Timer", "Google Drive Sync", "Local Database", "Windows & macOS & Android & iOS"],
65        primaryLink: "gazelist.html",
66        primaryLabel: "Details",
67        secondaryLink: null,
68        secondaryLabel: null,
69        privacyLink: "gazelist-privacy-policy.html"
70    },
71    {
72        id: "topicraft",
73        title: "Topicraft",
74        category: "productivity",
75        featured: true,
76        badge: "AI-Powered Micro-learning",
77        icon: "fa-solid fa-graduation-cap",
78        image: "assets/topicraft_logo.png",
79        description: "An AI-powered micro-learning platform that transforms any topic into interactive, gamified lesson maps in seconds. Learn through scientific spaced retrieval and active recall quests.",
80        specs: [
81            "AI-Powered Lesson Roadmap Generation (3-6 chapters)",
82            "Scientific Spaced Retrieval & Active Recall Quests",
83            "Multiple Card Types: Info, Multiple Choice, Match, & True/False",
84            "Gamification Engine with XP, Hearts, and Progression Bars"
85        ],
86        tags: ["Flutter", "Dart", "OpenAI API", "Micro-learning", "Gamification", "Cross-platform"],
87        primaryLink: "topicraft.html",
88        primaryLabel: "Details",
89        secondaryLink: null,
90        secondaryLabel: null,
91        privacyLink: "topicraft-privacy-policy.html"
92    },
93    {
94        id: "uyap-cevirici",
95        title: "UYAP Çevirici",
96        category: "legal",
97        featured: false,
98        badge: "Masaüstü Eklentisi",
99        icon: "fa-solid fa-file-word",
100        image: "assets/uyap_cevirici_logo.png",
101        description: "Google Dokümanlar™ ve UYAP (.udf) arasında biçimlendirme, liste ve görselleri kayıpsız koruyarak çift yönlü dönüşüm sağlayan, sunucusuz mimarisiyle %100 güvenli Google Workspace eklentisi.",
102        tags: ["Google Apps Script", "Google Docs API", "UDF Converter"],
103        primaryLink: "https://workspace.google.com/u/0/marketplace/app/uyap_%C3%A7evirici/46494924541?flow_type=2",
104        primaryLabel: "Workspace Market",
105        secondaryLink: null,
106        secondaryLabel: null,
107        privacyLink: "https://docs.google.com/document/d/1LR-iZAjOx-KvHIVGvq_rD-ggNL-kazE313tVN0KN1-E/edit?usp=drive_link",
108        termsLink: "https://docs.google.com/document/d/1E7JcIYNrASBJGuPS7mJ1Uvtl5zlyAAe8pR7OYr_5A6M/edit?usp=drive_link"
109    },
110    {
111        id: "uyap-indirici",
112        title: "UYAP İndirici",
113        category: "legal",
114        featured: false,
115        badge: "Tarayıcı Eklentisi",
116        icon: "fa-solid fa-cloud-arrow-down",
117        image: "assets/uyap_indirici_logo.png",
118        description: "UYAP Vatandaş ve Avukat portallarındaki dava dosyası evraklarını otomatik olarak tarayan, filtreleyen, indiren ve mahkeme/esas numarasına göre klasörleyen akıllı tarayıcı eklentisi.",
119        tags: ["Chrome Extension", "JavaScript", "UYAP Automation", "File Downloader", "Local Archive"],
120        primaryLink: "uyap-indirici.html",
121        primaryLabel: "Detaylar",
122        secondaryLink: "https://chromewebstore.google.com/detail/uyap-i%CC%87ndirici/lnddimcnbhiobmjicaajinebalhkkfjd?hl=tr&utm_source=ext_sidebar",
123        secondaryLabel: "Chrome Mağazası",
124        privacyLink: "uyap-indirici-gizlilik-politikasi.html"
125    },
126    {
127        id: "aka-manage-calendar",
128        title: "AKA Manage Calendar",
129        category: "productivity",
130        featured: false,
131        badge: "Masaüstü Eklentisi",
132        icon: "fa-solid fa-calendar-days",
133        image: "assets/aka_manage_calendar_logo.png",
134        description: "A Google Sheets add-on to manage your Google Calendar. Import calendar events to a spreadsheet, make edits directly, and sync changes back effortlessly.",
135        tags: ["Google Apps Script", "Calendar API", "Sheets API"],
136        primaryLink: "https://workspace.google.com/marketplace/app/aka_manage_calendar/189500482061?flow_type=2",
137        primaryLabel: "Workspace Market",
138        secondaryLink: "https://docs.google.com/document/d/19GNkEbijz8NM67Slep9rG_Oj47UuDeDtzXfztLE3Gg0/edit?usp=drive_link",
139        secondaryLabel: "FAQ",
140        privacyLink: "https://docs.google.com/document/d/1Jacmk31uC3ZyXc2IcHkNnZ4UR9JG1lS5_8Bk-L_2C9I/edit?usp=drive_link",
141        termsLink: "https://docs.google.com/document/d/1OTaf-fy37WqbtvKoRt9cx7RnbLNJJv7QCzUCKcof-fM/edit?usp=drive_link"
142    },
143    {
144        id: "aka-ticked-tasks",
145        title: "AKA Ticked Tasks",
146        category: "productivity",
147        featured: false,
148        badge: "Masaüstü Eklentisi",
149        icon: "fa-solid fa-list-check",
150        image: "assets/aka_ticked_tasks_logo.png",
151        description: "A Google Sheets add-on to download and analyze completed Google Tasks. Export task details, view completion statistics, and measure adherence to due dates.",
152        tags: ["Google Apps Script", "Tasks API", "Data Analytics"],
153        primaryLink: "https://workspace.google.com/u/0/marketplace/app/aka_ticked_tasks/409148054319?flow_type=2",
154        primaryLabel: "Workspace Market",
155        secondaryLink: "#",
156        secondaryLabel: "Support",
157        privacyLink: "https://docs.google.com/document/d/1rBKscDN-bbinsbZV-ZYFpKEJMm8h4hQ3Ufb148z0KLY/edit?usp=drive_link",
158        termsLink: "https://docs.google.com/document/d/1Ynn5EepzCedaAKbN8vyH
158B3pU96Bl-vdWfDxBk2yM_G4/edit?usp=drive_link"
159    }
160];
161
162// Inject App Cards
163const appGrid = document.getElementById('appGrid');
164
165function renderApps(filterCategory = 'all') {
166    appGrid.innerHTML = '';
167    
168    const filteredApps = filterCategory === 'all' 
169        ? appsData 
170        : appsData.filter(app => app.category === filterCategory);
171        
172    filteredApps.forEach(app => {
173        const card = document.createElement('div');
174        card.className = `app-card ${app.featured ? 'featured' : ''}`;
175        card.setAttribute('data-category', app.category);
176        
177        // Tags HTML
178        const tagsHTML = app.tags.map(tag => `<span class="tech-tag">${tag}</span>`).join('');
179        
180        // Footer Buttons HTML
181        let footerButtonsHTML = '';
182        if (app.primaryLink) {
183            footerButtonsHTML += `<a href="${app.primaryLink}" class="app-link app-link-primary"><i class="fa-solid fa-download"></i> ${app.primaryLabel}</a>`;
184        }
185        if (app.secondaryLink) {
186            let iconClass = 'fa-solid fa-circle-info';
187            if (app.secondaryLink.includes('play.google.com')) {
188                iconClass = 'fa-brands fa-google-play';
189            } else if (app.secondaryLink.includes('chromewebstore.google.com')) {
190                iconClass = 'fa-brands fa-chrome';
191            }
192            footerButtonsHTML += `<a href="${app.secondaryLink}" target="_blank" class="app-link app-link-secondary"><i class="${iconClass}"></i> ${app.secondaryLabel}</a>`;
193        }
194
195        // Get category label
196        const categoryLabel = app.badge || 'Masaüstü Uygulaması';
197
198        // Legal Links HTML
199        let legalLinksHTML = '';
200        if (app.privacyLink || app.termsLink) {
201            legalLinksHTML = `
202                <div class="app-legal-links">
203                    ${app.privacyLink ? `<a href="${app.privacyLink}" target="_blank" class="legal-link"><i class="fa-solid fa-shield-halved"></i> Privacy Policy</a>` : ''}
204                    ${app.termsLink ? `<a href="${app.termsLink}" target="_blank" class="legal-link"><i class="fa-solid fa-scale-balanced"></i> Terms</a>` : ''}
205                </div>
206            `;
207        }
208
209        // Specs List HTML (only for featured/asymmetric layout)
210        let specsHTML = '';
211        if (app.featured && app.specs) {
212            const listItems = app.specs.map(spec => `<li class="spec-item"><i class="fa-solid fa-square-check"></i> <span>${spec}</span></li>`).join('');
213            specsHTML = `
214                <div class="app-specs-panel">
215                    <span class="spec-title">[ Yetenekler & Özellikler ]</span>
216                    <ul class="spec-list">
217                        ${listItems}
218                    </ul>
219                </div>
220            `;
221        }
222
223        // Inside card html depends on featured or not
224        if (app.featured) {
225            card.innerHTML = `
226                <div class="app-card-layout">
227                    <div class="app-featured-split">
228                        <div>
229                            ${app.image ? `<div class="app-preview-container"><img class="app-preview" src="${app.image}" alt="${app.title} preview"></div>` : ''}
230                            <div class="app-header">
231                                <div class="app-icon">
232                                    <i class="${app.icon}"></i>
233                                </div>
234                                <div class="app-title-group">
235                                    <h3>${app.title}</h3>
236                                    <span class="app-category">${categoryLabel}</span>
237                                </div>
238                            </div>
239                            <div class="app-body">
240                                <p>${app.description}</p>
241                                <div class="tech-tags">
242                                    ${tagsHTML}
243                                </div>
244                                ${legalLinksHTML}
245                            </div>
246                        </div>
247                        ${specsHTML}
248                    </div>
249                    <div class="app-footer">
250                        ${footerButtonsHTML}
251                    </div>
252                </div>
253            `;
254        } else {
255            card.innerHTML = `
256                <div class="app-card-layout">
257                    <div>
258                        ${app.image ? `<div class="app-preview-container"><img class="app-preview" src="${app.image}" alt="${app.title} preview"></div>` : ''}
259                        <div class="app-header">
260                            <div class="app-icon">
261                                <i class="${app.icon}"></i>
262                            </div>
263                            <div class="app-title-group">
264                                <h3>${app.title}</h3>
265                                <span class="app-category">${categoryLabel}</span>
266                            </div>
267                        </div>
268                        <div class="app-body">
269                            <p>${app.description}</p>
270                            <div class="tech-tags">
271                                ${tagsHTML}
272                            </div>
273                            ${legalLinksHTML}
274                        </div>
275                    </div>
276                    <div class="app-footer">
277                        ${footerButtonsHTML}
278                    </div>
279                </div>
280            `;
281        }
282        appGrid.appendChild(card);
283    });
284}
285
286// Sliding Indicator Logic for Filter Buttons
287const filterIndicator = document.getElementById('filterIndicator');
288const filterControls = document.getElementById('filterControls');
289const filterButtons = document.querySelectorAll('.filter-btn');
290
291function updateFilterIndicator(activeBtn) {
292    if (!filterIndicator || !activeBtn) return;
293    
294    // Offset relative to the parent (.filter-controls)
295    const leftOffset = activeBtn.offsetLeft;
296    const buttonWidth = activeBtn.offsetWidth;
297    
298    filterIndicator.style.left = `${leftOffset}px`;
299    filterIndicator.style.width = `${buttonWidth}px`;
300}
301
302// Attach filter button actions
303filterButtons.forEach(btn => {
304    btn.addEventListener('click', () => {
305        filterButtons.forEach(b => b.classList.remove('active'));
306        btn.classList.add('active');
307        updateFilterIndicator(btn);
308        
309        const filter = btn.getAttribute('data-filter');
310        renderApps(filter);
311    });
312});
313
314// Window resize listener to keep sliding indicator positioned correctly
315window.addEventListener('resize', () => {
316    const activeBtn = document.querySelector('.filter-btn.active');
317    updateFilterIndicator(activeBtn);
318});
319
320// Live Terminal Typing Simulation Ticker in Hero
321const terminalBody = document.getElementById('terminalBody');
322const terminalLogs = [
323    { type: 'command', text: 'parse-udf --file="karar_tutanak_2026.udf"' },
324    { type: 'status', text: 'Reading binary UDF header structure...' },
325    { type: 'success', text: '[OK] Header verified. XML payload found (Size: 312KB).' },
326    { type: 'status', text: 'Decrypting embedded electronic signature...' },
327    { type: 'success', text: '[OK] E-Signature: Valid (Adalet Bakanligi Sertifikasi).' },
328    { type: 'command', text: 'convert-tiff-to-pdf --input="tarama_ek_03.tiff"' },
329    { type: 'status', text: 'Enhancing scan contrast & reducing backgrounds...' },
330    { type: 'success', text: '[OK] Contrast calibrated. Compression ratio: 4.8x.' },
331    { type: 'success', text: '[OK] PDF generated: tarama_ek_03.pdf (824 KB).' },
332    { type: 'command', text: 'sync-google-calendar --sheet="AKA Court Hearings"' },
333    { type: 'status', text: 'Authenticating with Google Workspace API...' },
334    { type: 'success', text: '[OK] Retrieved 8 events. Synchronized with spreadsheet.' },
335    { type: 'command', text: 'gazelist-sync --account="[email protected]"' },
336    { type: 'status', text: 'Verifying database checksums & syncing with Drive...' },
337    { type: 'success', text: '[OK] Merged 42 local and 12 remote tasks. 0 conflicts.' },
338    { type: 'command', text: 'sozgec-scan --target="eksi_yazarlar"' },
339    { type: 'status', text: 'Yazar troll skorları yerel veritabanından taranıyor...' },
340    { type: 'success', text: '[TAMAM] Yazar troll skoru: %82. Rahatsız edici içerik gizlendi.' },
341    { type: 'command', text: 'sozgec-report --author="troll_yazar_99"' },
342    { type: 'status', text: 'Yazar girdileri analiz ediliyor & Yap
342ay Zekaya iletiliyor...' },
343    { type: 'success', text: '[TAMAM] Yapay Zeka analiz puanı hesaplandı. Liste güncellendi.' }
344];
345
346let logIndex = 0;
347let terminalLineNumber = 6;
348
349function appendTerminalLog() {
350    if (!terminalBody) return;
351    
352    const log = terminalLogs[logIndex];
353    const logElement = document.createElement('div');
354    logElement.className = 'terminal-line';
355    
356    let spanClass = 'muted';
357    let textHTML = log.text;
358    
359    if (log.type === 'command') {
360        textHTML = `$ <span class="accent">${log.text}</span>`;
361    } else if (log.type === 'status') {
362        textHTML = `<span class="muted">[status]</span> ${log.text}`;
363    } else if (log.type === 'success') {
364        textHTML = `<span class="success">[ok]</span> ${log.text}`;
365    }
366    
367    logElement.innerHTML = `<span class="muted">${terminalLineNumber}  </span>${textHTML}`;
368    terminalBody.appendChild(logElement);
369    
370    // Auto-scroll to show latest logs
371    terminalBody.scrollTop = terminalBody.scrollHeight;
372    
373    // Prune top logs if too many lines to keep widget clean
374    const lines = terminalBody.querySelectorAll('.terminal-line');
375    if (lines.length > 9) {
376        lines[0].remove();
377    }
378    
379    // Increment log settings
380    logIndex = (logIndex + 1) % terminalLogs.length;
381    terminalLineNumber++;
382}
383
384// Initialize Render & Animations
385document.addEventListener('DOMContentLoaded', () => {
386    renderApps('all');
387    
388    // Initialize filter capsule
389    const activeBtn = document.querySelector('.filter-btn.active');
390    setTimeout(() => {
391        updateFilterIndicator(activeBtn);
392    }, 100);
393    
394    // Start terminal logs ticker
395    setInterval(appendTerminalLog, 2500);
396});
397
398// Dynamic Header Styling on Scroll
399window.addEventListener('scroll', () => {
400    const header = document.querySelector('header');
401    if (window.scrollY > 50) {
402        header.style.padding = '0.3rem 0';
403        header.style.backgroundColor = 'rgba(12, 12, 11, 0.95)';
404    } else {
405        header.style.padding = '0';
406        header.style.backgroundColor = 'rgba(12, 12, 11, 0.85)';
407    }
408});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.