News:

SMF - Just Installed!

Main Menu

Recent posts

#71
Announcements & Releases / v1.1.14
Last post by hitsumo - Jul 19, 2026, 03:28 AM
# Anime Tracker 1.1.14

**Release date:** 2026-07-17

## New: Filter by year

- **The main list page gains a "Filter by Year" filter.** A collapsible
  section, sitting between the broadcast-status filter and the letter filter,
  holds a grid of year checkboxes.
- **You can pick a single year or several.** Check just one year (e.g. 1972),
  a few years at once (e.g. 1972 + 1973), or non-contiguous years
  (e.g. 1972 + 1986 + 2004). Every anime whose year is among those selected is
  listed.
- **The years are generated automatically from the catalog.** The years in the
  boxes are not a hand-maintained list; they are derived from each anime's
  release date (`release_date`) and sorted descending. Add an anime from a new
  year and that year's checkbox appears on its own; remove the last anime of a
  year and the box disappears on its own. (Only anime with a release date are
  included in a year box.)
- **The selected year is highlighted instantly.** Checking a box fills the chip
  blue; unchecking turns it white immediately - so you see the current
  selection clearly even before pressing "Filter".
- **A "Clear year selection" button.** When a year filter is active, a button
  appears below the year section that clears only the year selection in one
  click, while preserving your other filters (search, genre, watch status,
  letter, emotion, page size, active tab).
- **The filter keeps your current search, sort and pagination.** The selected
  years are preserved as you move between sort links, the letter filter and
  page numbers.

## Improvement: help pages "back" link

- **The "Back to Home" / "Help Contents" links on the help pages now look like
  buttons.** They render as an outlined button instead of plain blue text, and
  the leading arrow was removed. Their behaviour is unchanged.

## Housekeeping

- **Two dead files removed:** `files/user_anime_helpers.php` (it had become a
  byte-for-byte duplicate of `functions/user_anime_helpers.php` and was
  referenced from nowhere) and `files/dizin_listesi.txt` (an old directory-dump
  artifact). When updating a server install you may delete these two files if
  present; there is no functional impact.

## How it works (technical)

- The filter is selected with the `year_filter[]` array parameter. Year is not
  a separate column; the predicate runs on the existing `animes.release_date`
  column as `YEAR(a.release_date) IN (...)`. No new table, column or setting is
  needed.
- Selected year values are cast to `(int)` on the server and whitelisted
  against the years that actually exist in the catalog; only validated integers
  are embedded in the SQL, so there is no injection surface.
- The chip highlight is bound to the live checkbox state rather than a
  server-side class (`:has(input:checked)` plus a small JS sync), so unchecking
  removes the highlight instantly.

## Schema / migration

- `migration/1.1.14/upgrade.sql` only advances the version to 1.1.14; there is
  **no schema change** (no SQL statement to run). The central catalog is not
  affected and requires no manual step.

## Changed / new files

- index.php (Filter by year: parameter parsing, `YEAR(release_date) IN (...)`
  predicate in both query branches, selected years preserved across
  sort/letter/pagination links, filter-form UI, chip-sync JS)
- css/series.css (year grid and chip styles, "Clear year selection" button)
- css/help.css (button look for the help-page "back" link)
- lang/tr.php, lang/en.php (index.filter.year / year_none / year_clear keys;
  removal of the leading arrow from help.back_to_home / back_to_index)
- migration/1.1.14/upgrade.sql (new)
- version.txt
- Removed: files/user_anime_helpers.php, files/dizin_listesi.txt
#72
Duyurular ve Sürümler / v1.1.14
Last post by hitsumo - Jul 19, 2026, 03:27 AM
# Anime Tracker 1.1.14

**Yayin tarihi:** 2026-07-17

## Yeni: Yila gore filtre

- **Ana liste sayfasina "Yila Gore Filtrele" filtresi eklendi.** Yayin durumu
  filtresi ile harf filtresi arasinda duran, acilir-kapanir bir bolum icinde
  yil onay kutulari (checkbox) yer alir.
- **Tek ya da birden cok yil secebilirsiniz.** Sadece tek bir yili
  (orn. 1972) isaretleyebilir, birkac yili birden (orn. 1972 + 1973) ya da
  bitisik olmayan yillari (orn. 1972 + 1986 + 2004) ayni anda secebilirsiniz.
  Secili yillari iceren tum animeler listelenir.
- **Yillar katalogtan otomatik gelir.** Kutulardaki yillar elle tutulan bir
  liste degildir; katalogdaki animelerin yayin tarihinden (`release_date`)
  turetilir ve azalan sirada dizilir. Yeni bir yila ait anime eklediginizde
  o yilin kutusu kendiliginden ortaya cikar; o yila ait anime kalmazsa kutu
  kendiliginden kaybolur. (Yalniz yayin tarihi girili animeler bir yil
  kutusuna dahil olur.)
- **Secili yil aninda vurgulanir.** Bir kutuyu isaretlediginizde cip mavi
  dolar, isareti kaldirdiginizda aninda beyaza doner - "Filtrele"ye basmadan
  once bile secili durumu net gorursunuz.
- **"Yil secimini temizle" butonu.** Aktif bir yil filtresi varken yil
  bolumunun altinda cikan bu buton, diger filtrelerinizi (arama, tur, izleme
  durumu, harf, duygu, sayfa boyutu, aktif sekme) koruyarak yalnizca yil
  secimini tek tiklamada temizler.
- **Filtre mevcut aramanizi, siralamanizi ve sayfalamanizi korur.** Secili
  yillar; siralama baglantilari, harf filtresi ve sayfa numaralari arasinda
  gezerken korunur.

## Iyilestirme: Yardim sayfalarindaki "geri don" baglantisi

- **Yardim sayfalarindaki "Ana Sayfaya Don" / "Yardim Icindekiler"
  baglantilari artik buton gorunumunde.** Duz mavi yazi yerine cerceveli buton
  olarak gorunur; basindaki ok isareti kaldirildi. Islevi degismedi.

## Temizlik

- **Iki olu dosya kaldirildi:** `files/user_anime_helpers.php` (artik
  `functions/user_anime_helpers.php` ile birebir ayni bir kopyaydi ve hicbir
  yerden cagrilmiyordu) ve `files/dizin_listesi.txt` (eski bir dizin dokumu
  artefakti). Sunucuya kurulumu guncellerken bu iki dosya varsa elle
  silinebilir; islevsel bir etkisi yoktur.

## Nasil calisir (teknik)

- Filtre `year_filter[]` dizi parametresiyle secilir. Yil ayri bir kolon
  degildir; predikat mevcut `animes.release_date` kolonu uzerinde
  `YEAR(a.release_date) IN (...)` olarak calisir. Yeni tablo, alan veya ayar
  gerekmez.
- Secilen yil degerleri sunucuda `(int)`'e cast edilir ve yalnizca katalogda
  gercekten bulunan yillarla eslesecek sekilde beyaz listeye alinir; SQL'e
  yalnizca dogrulanmis tamsayilar gomulur, boylece enjeksiyon yuzeyi yoktur.
- Cip vurgusu sunucu tarafi bir sinifa degil canli checkbox durumuna baglidir
  (`:has(input:checked)` + kucuk bir JS senkronu), bu yuzden isareti
  kaldirinca vurgu aninda kalkar.

## Sema / migration

- `migration/1.1.14/upgrade.sql` yalnizca surumu 1.1.14'e tasir; **sema
  degisikligi yoktur** (calistirilacak SQL ifadesi yok). Merkez katalog
  etkilenmez, sunucuda elle bir islem GEREKMEZ.

## Degisen / yeni dosyalar

- index.php (Yila gore filtre: parametre ayristirma, iki sorgu dalinda
  `YEAR(release_date) IN (...)` predikati, secili yillarin siralama/harf/
  sayfalama baglantilarinda korunmasi, filtre formu arayuzu, cip senkron JS'i)
- css/series.css (yil izgarasi ve cip stilleri, "Yil secimini temizle" butonu)
- css/help.css (yardim sayfasi "geri don" baglantisinin buton gorunumu)
- lang/tr.php, lang/en.php (index.filter.year / year_none / year_clear
  anahtarlari; help.back_to_home / back_to_index metinlerinden ok isaretinin
  kaldirilmasi)
- migration/1.1.14/upgrade.sql (yeni)
- version.txt
- Kaldirildi: files/user_anime_helpers.php, files/dizin_listesi.txt
#73
Announcements & Releases / v1.1.13
Last post by hitsumo - Jul 16, 2026, 05:45 PM
# Anime Tracker 1.1.13

**Release date:** 2026-07-16

## New: Personal list tab

- **The main list page now has "General List" / "Personal List" tabs.** A
  slim tab bar sits between the pagination bar and the list table.
  - **General List** - the whole catalog (the previous default behaviour;
    nothing changed).
  - **Personal List** - only the anime you have set a watch status on. That
    is, every status EXCEPT "Not Selected": Watched, Watching, Plan to Watch,
    On Hold, Dropped.
- **An anime enters your personal list the moment you pick a status.**
  Setting an anime's status to anything other than "Not Selected" (via the
  in-list +/- controls or the details page) makes it appear on the Personal
  List tab. Setting it back to "Not Selected" removes it.
- **The tab keeps your current search, filters and sort.** While on the
  Personal List tab, the genre / status / letter / emotion filters and search
  all work as usual, scoped to anime with a selected status. Switching tabs
  returns you to the first page.
- **The tabs only show for users who have a personal list.** They are always
  visible on your own install (self-host). In multi-user mode a logged-out
  visitor has no personal list, so the tab bar is not shown to them.

## New: Default list preference

- **The List Settings page gains a "Default List" selector.** It chooses which
  tab is selected when the anime list page opens: **General List** (the previous
  behaviour) or **Personal List**. It is a dropdown, like the interface-language
  selector, and saves as soon as you pick a value.
- **It is per-user.** The preference affects only you (stored in the `user_pref`
  table) and never touches other users.
- **Clicking a tab overrides the preference.** Even if your default is Personal
  List, clicking the "General List" tab switches you for that visit; the next
  time you open the page your default is applied again.

## New: List Settings tabs

- **The List Settings page is now split into tabs.** There are three:
  - **Import/Export** - Export List, Import List, Import MyAnimeList List,
    Import AniList List.
  - **General Settings** - Interface Language, Title Language, Default List,
    Adult Content.
  - **Management Settings** - Genres, Tags, Catalog Sync, Episode Count Sync,
    Update. This tab (both its button and panel) is shown only to
    **moderators/admins** and the **self-host owner**; a regular online member
    never sees it (every section inside was already behind a capability gate;
    now the tab itself is hidden too).
  - **Cleanup** - Clear List. Moved to its own tab because it is a destructive
    action, and shown only to **admins** and the **self-host owner** (button and
    panel gated by `canAdmin`; a regular online member and moderators do not see
    it).
- **Switching tabs is instant, with no page reload.** The open tab is
  remembered in the browser; after an import or a sync reloads the page, the
  same tab stays open.
- **Nothing is lost with JavaScript off.** The tab bar is hidden and all
  sections stack as before (progressive enhancement) - no section was moved,
  only grouped.

## How it works (technical)

- The tab is selected with the `?view=personal` URL parameter and is a pure
  query-scope view: it adds `AND ua.watch_status IS NOT NULL` to the main
  list's existing `user_anime` LEFT JOIN. No new table, column or setting is
  needed.
- An invalid or unauthorized `view` value silently falls back to "General
  List" (including for anonymous online visitors), so it cannot be forced via
  the parameter.
- The default-list preference is stored in the per-user `user_pref` key
  `list_view_default` ('all' / 'personal') and written by a new CSRF-protected
  POST endpoint `set_list_view_pref.php`. An explicit `?view=` in the URL (a tab
  click) always overrides the preference, so the tabs always send an explicit
  view and the preserved sort/filter/search links carry the view only when it
  differs from the preference.

## Schema / migration

- `migration/1.1.13/upgrade.sql` only advances the version to 1.1.13; there is
  **no schema change** (no SQL statement to run). The central catalog is not
  affected and requires no manual step.

## Changed / new files

- index.php (General/Personal tab bar, view scope, default-preference cascade,
  tab preserved across filter/search/sort/pagination links, tab CSS)
- list_settings.php (Default List selector section + Import/Export & General
  tabs: tab bar, panel wrappers, tab CSS and JS switching)
- set_list_view_pref.php (new - CSRF-protected preference endpoint)
- lang/tr.php, lang/en.php (index.tab.* + list_settings.section.list_view.* +
  list_settings.tab.*)
- migration/1.1.13/upgrade.sql (new)
- version.txt
#74
Duyurular ve Sürümler / v1.1.13
Last post by hitsumo - Jul 16, 2026, 05:45 PM
# Anime Tracker 1.1.13

**Yayin tarihi:** 2026-07-16

## Yeni: Kisisel liste sekmesi

- **Ana liste sayfasina "Genel Liste" / "Kisisel Liste" sekmeleri eklendi.**
  Sayfalama cubugu ile liste tablosu arasinda duran ince bir sekme cubugu.
  - **Genel Liste** - katalogun tamami (onceki varsayilan davranis; hicbir
    sey degismedi).
  - **Kisisel Liste** - yalnizca izleme durumu SECTIGINIZ animeler. Yani
    "Secim Yapilmamis" DISINDAKI her durum burada gorunur: Izlendi,
    Izleniyor, Izlenme Planlandi, Izleme Ertelendi, Izleme Birakildi.
- **Durum sectiginiz an anime kisisel listenize girer.** Bir animenin
  durumunu "Secim Yapilmamis" disinda herhangi bir degere ayarlamak
  (liste ici +/- ile veya detay sayfasindan) onu Kisisel Liste sekmesinde
  gorunur kilar. Durumu tekrar "Secim Yapilmamis" yaparsaniz kisisel
  listeden cikar.
- **Sekme mevcut aramanizi, filtrelerinizi ve siralamanizi korur.** Kisisel
  Liste sekmesindeyken tur / durum / harf / duygu filtreleri ve arama aynen
  calisir; yalniz secili duruma sahip animeler uzerinde. Sekme degistirince
  ilk sayfaya donulur.
- **Sekmeler yalniz kisisel listesi olan kullaniciya gosterilir.** Kendi
  kurulumunuzda (self-host) her zaman gorunur. Cok kullanicili surumde giris
  yapmamis ziyaretcinin kisisel listesi olmadigindan sekme cubugu onlara hic
  cikmaz.

## Yeni: Varsayilan liste tercihi

- **Liste Ayarlari sayfasina "Varsayilan Liste" secimi eklendi.** Anime listesi
  sayfasi acildiginda hangi sekmenin secili gelecegini belirlersiniz: **Genel
  Liste** (onceki davranis) veya **Kisisel Liste**. Arayuz-dili secimindeki gibi
  bir acilir menudur; sectiginiz an kaydedilir.
- **Kisi bazlidir.** Tercih yalniz sizi etkiler (`user_pref` tablosunda
  saklanir), diger kullanicilara dokunmaz.
- **Sekmeye tiklamak tercihi ezer.** Varsayilaniniz Kisisel Liste olsa bile
  ustteki "Genel Liste" sekmesine tiklayarak o an genel listeye gecebilirsiniz;
  bir sonraki acilista yine varsayilaniniz gelir.

## Yeni: Liste Ayarlari sekmeleri

- **Liste Ayarlari sayfasi sekmelere ayrildi.** Uc sekme var:
  - **Ice/Disa Aktar** - Listeyi Disa Aktar, Listeyi Ice Aktar, MyAnimeList
    Listesini Ice Aktar, AniList Listesini Ice Aktar.
  - **Genel Ayarlar** - Arayuz Dili, Baslik Dili, Varsayilan Liste, Yetiskin
    Icerik.
  - **Yonetim Ayarlari** - Turler, Etiketler, Katalog Senkronizasyonu, Bolum
    Sayisi Senkronizasyonu, Guncelleme. Bu sekme
    (butonu ve paneli) yalnizca **moderator/admin** ve **self-host sahibi** icin
    gorunur; online normal uye bu sekmeyi hic gormez (zaten icindeki her bolum
    yetki kapisinin arkasindaydi, simdi sekmenin kendisi de gizli).
  - **Temizleme** - Listeyi Temizle. Yikici bir islem oldugu icin kendi
    sekmesine alindi ve yalnizca **admin** ile **self-host sahibi** icin
    gorunur (buton ve panel `canAdmin` ile sarili; online normal uye ve
    moderator gormez).
- **Sekme gecisi aninda, sayfa yenilenmeden olur.** Acik sekme tarayıcıda
  hatirlanir; bir ice/disa aktarma veya senkronizasyon sonrasi sayfa yenilense
  bile ayni sekme acik kalir.
- **JS kapaliyken hicbir sey kaybolmaz.** Sekme cubugu gizlenir ve tum bolumler
  eskisi gibi alt alta gorunur (progressive enhancement) - hicbir bolum
  tasinmadi, yalniz gruplandi.

## Nasil calisir (teknik)

- Sekme, `?view=personal` URL parametresiyle secilir ve tamamen sorgu-kapsamli
  bir gorunumdur: ana listenin mevcut `user_anime` LEFT JOIN'ine
  `AND ua.watch_status IS NOT NULL` kosulu eklenir. Yeni tablo, alan veya ayar
  gerekmez.
- Gecersiz veya yetkisiz `view` degeri sessizce "Genel Liste"ye duser
  (anonim online ziyaretci dahil), yani parametre ile zorlanamaz.
- Varsayilan liste tercihi per-user `user_pref` anahtari
  `list_view_default`'ta ('all' / 'personal') tutulur; yeni endpoint
  `set_list_view_pref.php` (CSRF korumali, POST) yazar. URL'deki acik `?view=`
  parametresi (sekme tiklamasi) her zaman tercihi ezer, bu yuzden sekmeler
  daima acik view yollar ve korunan siralama/filtre/arama baglantilari view'i
  yalniz tercihten farkli oldugunda tasir.

## Sema / migration

- `migration/1.1.13/upgrade.sql` yalnizca surumu 1.1.13'e tasir; **sema
  degisikligi yoktur** (calistirilacak SQL ifadesi yok). Merkez katalog
  etkilenmez, sunucuda elle bir islem GEREKMEZ.

## Degisen / yeni dosyalar

- index.php (Genel/Kisisel sekme cubugu, view kapsami, varsayilan tercih
  cascade'i, sekmenin filtre/arama/siralama/sayfalama baglantilarinda
  korunmasi, sekme CSS'i)
- list_settings.php (Varsayilan Liste secim bolumu + Ice/Disa Aktar & Genel
  sekmeleri: sekme cubugu, panel sarmalamalari, sekme CSS'i ve JS gecisi)
- set_list_view_pref.php (yeni - CSRF korumali tercih endpoint'i)
- lang/tr.php, lang/en.php (index.tab.* + list_settings.section.list_view.* +
  list_settings.tab.*)
- migration/1.1.13/upgrade.sql (yeni)
- version.txt
#75
Announcements & Releases / v1.1.12
Last post by hitsumo - Jul 16, 2026, 08:50 AM
# Anime Tracker 1.1.12

**Release date:** 2026-07-15

## New: Invite request limit

- **The admin can cap how many invite requests may sit in the queue at once
  (e.g. 50, 70, 100).** Once the number of pending requests reaches the limit,
  the public invite-request form (request_invite.php) closes and no new request
  is accepted. Visitors see a "quota full, try again later" notice.
- **The limit counts PENDING requests, so it is self-healing.** When the admin
  invites or rejects a queued request, that slot reopens automatically. The cap
  is based on what is currently waiting, not on all requests ever submitted.
- **You can remove the limit at any time.** Setting the field to `0` removes the
  cap (unlimited) and reopens the form fully.
- The check has two lines: the form is hidden on GET when closed, and the submit
  (POST) side re-validates on the server (it cannot be bypassed with a direct
  POST).

## New: Registration announcement

- **The admin can write a free-text announcement shown on the registration page
  (register.php).** For example: "Invites are limited to 50 people." or "A new
  invite slot opens in one week." The text is not a fixed template - whatever the
  admin types is what appears.
- **Leaving it empty hides the announcement.** With the field blank, no notice is
  shown on the registration screen.
- The text is stored raw and safely escaped on output (no HTML injection); line
  breaks are preserved.

## Admin controls

- Both settings live on the **Registration & Invites** page (admin_invites.php)
  and can only be changed by an **admin**:
  - "Invite Request Limit" card (Invite Requests tab): numeric field 0..100000,
    0 = unlimited. The card shows live status (pending / limit, open or closed).
  - "Registration Announcement" card (Invites tab): free text up to 2000
    characters.

## How it works (technical)

- Two new values are kept in the `settings` key/value table
  (`invite_request_limit`, `register_announcement`); no dedicated schema field
  is needed.
- A new helper `invite_request_limit_state($pdo)` reads the limit and the
  pending count to decide whether the form is open or closed; on a query error
  it fails safe (leaves the form OPEN so legitimate visitors are not locked out).
- **No central-catalog impact** - the settings are app-side only, never sent to
  the central catalog server; NO manual step is required on that host.

## Fix: Turkish characters on the Help pages

- **The Help pages (help.php and the help/ sub-pages) were written in ASCII-safe
  form** (e.g. "Izleme Durumlari", "Nasil Calisir?", "Yardim Icindekiler"). All
  Help text now renders with proper Turkish characters (İ, ç, ğ, ı, ö, ş, ü). The
  content lives in the `help.*` keys of `lang/tr.php`; HTML tags, code samples,
  `#anchor` links, and technical terms (JST, TZ, AnimeSchedule, broadcast_day,
  etc.) are preserved. The English help (`lang/en.php`) was unchanged.
- **The "GitHub page" phrase in the Help footer is now a clickable link**
  (https://github.com/hitsumo/animetracker); it was previously plain text. In
  both the Turkish and English help.
- **A contact email was added to the Help index (help.php):** just below the
  blue line under the title and above the intro text,
  `at@animetracker.uzakdiyarlar.com` (clickable mailto). In both Turkish and
  English (`help.contact`).

## Schema / migration

- `migration/1.1.12/upgrade.sql` seeds the two setting keys with their defaults
  (`INSERT IGNORE`, never clobbers an existing value) and advances the version
  to 1.1.12. There is no schema change.

## Changed / new files

- functions/auth_helpers.php (invite_request_limit_state + 'full' in submit)
- request_invite.php (hide form + closed notice when the queue is full)
- admin/admin_invites.php (limit + announcement cards, admin-only POSTs)
- register.php (announcement banner)
- help.php (contact email line)
- lang/tr.php (invites + help Turkish-character fix + help.contact),
  lang/en.php (invites + footer/contact links), lang/admin_tr.php,
  lang/admin_en.php
- migration/1.1.12/upgrade.sql (new)
- version.txt
#76
Duyurular ve Sürümler / v1.1.12
Last post by hitsumo - Jul 16, 2026, 08:49 AM
# Anime Tracker 1.1.12

**Yayin tarihi:** 2026-07-15

## Yeni: Davetiye talep limiti

- **Yonetici, ayni anda kuyrukta bekleyebilecek davetiye talebi sayisina bir
  limit koyabilir (or. 50, 70, 100).** Bekleyen talep sayisi bu limite
  ulasinca herkese acik davetiye talep formu (request_invite.php) kapanir ve
  yeni talep alinmaz. Ziyaretciye "kontenjan dolu, sonra tekrar dene" bildirimi
  gosterilir.
- **Limit BEKLEYEN talepleri sayar; kendini onarir.** Yonetici bir talebi
  davet edince veya reddedince o slot yeniden acilir - yeni talep alinabilir
  hale gelir. Boylece limit, gecmis tum talepleri degil yalnizca su an isleme
  bekleyenleri baz alir.
- **Limiti istediginiz zaman kaldirabilirsiniz.** Alana `0` yazmak limiti
  kaldirir (sinirsiz) - formu tekrar tam acar.
- Kontrol iki hatlidir: form GET'te kapaliysa hic gosterilmez, ayrica gonderim
  (POST) tarafinda da sunucu yeniden dogrular (dogrudan POST ile asilamaz).

## Yeni: Kayit ekrani duyurusu

- **Yonetici, kayit sayfasinda (register.php) gosterilecek serbest metinli bir
  duyuru yazabilir.** Ornek: "Davetiye 50 kisiliktir." veya "Yeni davetiye
  slotu 1 hafta sonra acilacaktir." Metin secmeli/kaliplasmis degildir; yonetici
  ne yazarsa o gosterilir.
- **Bos birakmak duyuruyu gizler.** Duyuru alani bosken kayit ekraninda hicbir
  not cikmaz.
- Metin ham saklanir, ciktida guvenli kacislanir (HTML enjeksiyonu yok); satir
  sonlari korunur.

## Yonetici kontrolleri

- Her iki ayar da **Kayit ve Davetler** (admin_invites.php) sayfasindadir ve
  **yalnizca yonetici** tarafindan degistirilebilir:
  - "Davetiye Talep Limiti" karti (Davetiye Talepleri sekmesi): sayisal alan
    0..100000, 0 = sinirsiz. Kartta canli durum gosterilir (bekleyen / limit,
    form acik mi kapali mi).
  - "Kayit Ekrani Duyurusu" karti (Davetler sekmesi): 2000 karaktere kadar
    serbest metin.

## Nasil calisir (teknik)

- Iki yeni deger `settings` anahtar/deger tablosunda tutulur
  (`invite_request_limit`, `register_announcement`); ayri bir sema alani
  gerektirmez.
- Yeni yardimci `invite_request_limit_state($pdo)` limiti ve bekleyen talep
  sayisini okuyup formun acik/kapali oldugunu belirler; sorgu hatasinda
  guvenli tarafta kalir (formu ACIK birakir, mesru ziyaretciyi kilitlemez).
- **Merkez katalog etkisi yoktur** - ayarlar yalnizca app tarafindadir, merkez
  katalog sunucusuna hic gitmez; sunucuda elle bir islem GEREKMEZ.

## Duzeltme: Yardim sayfasi Turkce karakterleri

- **Yardim sayfalarinin (help.php ve help/ alt sayfalari) icerigi ASCII-guvenli
  yazilmisti** (or. "Izleme Durumlari", "Nasil Calisir?", "Yardim Icindekiler").
  Tum yardim metinleri artik dogru Turkce karakterlerle gosterilir
  (İ, ç, ğ, ı, ö, ş, ü). Icerik `lang/tr.php` icindeki `help.*` anahtarlarindadir;
  HTML etiketleri, kod ornekleri, capa (#anchor) baglantilari ve teknik terimler
  (JST, TZ, AnimeSchedule, broadcast_day vb.) korunmustur. Ingilizce yardim
  (`lang/en.php`) degismedi.
- **Yardim sayfasi alt bilgisindeki "GitHub sayfasi" ifadesi artik tiklanabilir
  bir baglantidir** (https://github.com/hitsumo/animetracker); daha once duz
  metindi. Hem Turkce hem Ingilizce yardimda.
- **Yardim ana sayfasina (help.php) iletisim e-postasi eklendi:** basliktaki
  mavi cizginin hemen altinda, giris metninin ustunde
  `at@animetracker.uzakdiyarlar.com` (tiklanabilir mailto). Hem Turkce hem
  Ingilizce (`help.contact`).

## Sema / migration

- `migration/1.1.12/upgrade.sql` iki ayar anahtarini varsayilanlariyla tohumlar
  (`INSERT IGNORE`, mevcut degeri ezmez) ve surumu 1.1.12'ye tasir. Sema
  degisikligi yoktur.

## Degisen / yeni dosyalar

- functions/auth_helpers.php (invite_request_limit_state + submit'te 'full')
- request_invite.php (kuyruk doluysa formu gizle + kapali bildirimi)
- admin/admin_invites.php (limit + duyuru kartlari, admin-only POST'lar)
- register.php (duyuru banneri)
- help.php (iletisim e-postasi satiri)
- lang/tr.php (davetiye + yardim Turkce karakter duzeltmesi + help.contact),
  lang/en.php (davetiye + footer/iletisim linkleri), lang/admin_tr.php,
  lang/admin_en.php
- migration/1.1.12/upgrade.sql (yeni)
- version.txt
#77
Announcements & Releases / v1.1.11
Last post by hitsumo - Jul 15, 2026, 10:59 AM
Anime Tracker 1.1.11

Release date:** 2026-07-15

New: AniList import source limit

- **In online (multi-user) mode, a normal member may import from at most 3
  DIFFERENT AniList accounts.** This stops a single member from pulling an
  unbounded number of other people's public lists and flooding the moderation
  queue / catalog.

  - **The same account can be re-synced without limit.** An account you have
    already imported can be pulled again as often as you like without spending
    a new slot (a legitimate case: keep using AniList and come back later to
    re-import).

  - **A slot is consumed only on a real, successful import.** A mistyped name,
    previewing and cancelling, or an error never burns a slot; you can preview
    as much as you like.

  - Usernames are case-insensitive: `Mahmut`, `mahmut` and `MAHMUT` are one
    slot.

 Exemptions

- **Self-host (single-user) installs are never limited** - the sole owner may
  import from as many different names as they want.

- **Moderators and above are exempt** - bulk seeding is their legitimate job.

## Admin controls

- **The limit is configurable.** On the Admin Capabilities page, the "AniList
  import source limit" field sets the number of different accounts (default 3).
  **Setting 0 removes the limit (unlimited)** - an emergency off-valve.

- **An admin can reset a user's limit.** On the User Management page, every
  member who has used sources has a "Reset" button on their row; it clears that
  user's recorded sources so they regain the full allowance.

## How it works (technical)

- A new app-side table `anilist_import_sources` records the DISTINCT AniList
  names each member has used (one row per user, `(user_id, username)` UNIQUE).
  Used-source count = that user's row count.

- The check has two lines: at preview time (WITHOUT hitting AniList, no wasted
  call) and at import time (second defense + recording).

- The limit value lives in the `settings.anilist_import_source_limit` key; it
  needs no dedicated schema column.

- **No central-catalog impact** - this table is app-side only and never reaches
  the central catalog server; no manual step is required there.

## Improvement: Long dropdowns capped at 8 rows

- **Long dropdowns (more than 8 options) now show at most 8 rows, the rest
  scrolling.** For example the main list's "Filter by Genre" and the long
  selects on the form/detail pages used to cover almost the whole screen when
  opened; they are now compact, scrollable menus.

- **Applies site-wide:** the rule is not tied to one menu - every native
  `<select>` with more than 8 options is capped automatically; short menus
  (<=8) stay native.

- On desktop (mouse) the native `<select>` is enhanced into a compact menu;
  the selection is still written to the same form field (submit/filtering
  behavior unchanged). Touch devices keep the native picker. With JS off, the
  native list keeps working.

- `required` menus keep working (the native select is hidden but stays
  focusable, so browser validation is not broken). A very special menu (e.g.
  the genre-ADD picker that resets its own value) can be exempted with
  `data-no-enhance`.

## Security / deployment: main-app .htaccess

- **Added a dedicated `.htaccess` for the main-app document root (`files/`).**
  It 301-redirects http to https and sends HSTS, so the session cookie (written
  with the `Secure` flag in db.php over HTTPS) is always sent - removing the
  "logged in over https but logged out over http" symptom.

- Also: directory listing off, sensitive files denied (config.php, *.sql,
  *.md/*.txt, dotfiles), no web access to include/tooling dirs (functions/,
  migration/, tek_kullanimlik/), and no PHP execution under uploads/. PHP is
  NOT default-denied (the app's endpoints stay public) - this differs from the
  CENTRAL CATALOG server's default-deny `.htaccess`; the two must not be mixed.

## Schema / migration

- `migration/1.1.11/upgrade.sql` creates the new table (idempotent,
  `CREATE TABLE IF NOT EXISTS`). Fresh installs get it from `schema.sql`.

## Changed / new files

- functions/anilist_import_helpers.php (limit helpers)
- list_settings.php (preview + import limit checks, source recording)
- admin/admin_capabilities.php (global limit setting)
- admin/admin_users.php (per-user limit reset)
- lang/tr.php, lang/en.php, lang/admin_tr.php, lang/admin_en.php
- schema.sql (anilist_import_sources table)
- migration/1.1.11/upgrade.sql (new)
- js/select_enhance.js (new - generic dropdown enhancer)
- css/components.css (custom dropdown styles)
- index.php, add_anime.php, edit_anime.php, list_settings.php,
  anime_details.php, admin/admin_users.php, admin/admin_invites.php
  (select_enhance.js script tag; data-no-enhance on the add/edit genre-add
  picker)
- .htaccess (new - main-app docroot: HTTPS enforcement + HSTS + hardening)
- version.txt
#78
Announcements & Releases / v1.1.10
Last post by hitsumo - Jul 14, 2026, 10:44 AM
Anime Tracker 1.1.10

 Release date:** 2026-07-14

New feature

- **Three new broadcast-status values.** An anime's broadcast status is no longer
  limited to "Currently Airing" and "Finished Airing"; three more states can now
  be chosen:
  - **Not Yet Aired** - upcoming anime that has not started airing.
  - **Not Selected** - unspecified / unknown status. New anime forms now default
    to this value, so adding an anime no longer forces a finished/ongoing guess.
  - **Cancelled** - anime whose broadcast was cancelled.
- The new states appear in the add/edit status dropdown, the broadcast-status
  filter on the main page, and the statistics/display surfaces.
- **Automatic "Not Yet Aired" -> "Currently Airing" transition.** "Not Yet Aired"
  is not a dead end: when an anime actually starts broadcasting it flips to
  "Currently Airing" on its own - just as "Currently Airing -> Finished" is
  already automatic. This completes the broadcast-status lifecycle.

 How it works (technical)

- Three values were APPENDED to the `animes.status` enum (and its twin
  `catalog_requests.status`) - appended in place so existing rows keep their
  ordinal and no data is rewritten. Applied automatically on every install via
  `migration/1.1.10/upgrade.sql` (MODIFY is idempotent / re-run-safe).

- Broadcast-status labelling is now single-sourced through the new
  `broadcast_status_helpers.php` (`broadcast_status_label()` /
  `broadcast_status_options()`), replacing the if/elseif that was duplicated at
  every render surface - the same pattern as the watch_status helper family.

- Language-aware labels: the new states are translated in the English UI too
  (`index.broadcast.not_started` / `.unselected` / `.cancelled`).

## Import mapping

- **AniList** status now maps almost one-to-one (previously five states folded
  into two): FINISHED -> Finished, RELEASING/HIATUS -> Ongoing,
  NOT_YET_RELEASED -> Not Yet Aired, CANCELLED -> Cancelled.
- **AnimeSchedule** auto-fill: "Upcoming" -> "Not Yet Aired".
- Unknown / status-less imports (the legacy MAL export carries no airing status)
  now default to "Not Selected" instead of "Finished".

## Automatic transition (Not Yet Aired -> Currently Airing)

- The aired sync (`syncAllOngoingAiredEpisodes`, run from the page and from cron
  via `sync_aired.php`) now sweeps "Not Yet Aired" rows in addition to
  "Currently Airing" ones. The moment AnimeSchedule's timetable shows such a row
  with an ALREADY-aired episode (future-dated episodes are skipped by
  `isTimetableRowAired`), broadcast has begun, so the row is promoted to
  "Currently Airing" (or straight to "Finished" if its whole raw run has already
  aired). No extra API calls - the same weekly timetable request that updates
  ongoing shows also catches the ones that just started. A new `started` counter
  is added to the sync summary (web message + cron STDOUT).
- Limit: promotion only works for animes that have an `anime_schedule_link` and a
  `mal_id`; a "Not Yet Aired" anime lacking those must be moved by hand.
  Promotion does not compute `next_episode_date` (the aired sync never does), so
  the countdown still relies on `broadcast_day`/`broadcast_time` (cosmetic).

## Maintenance tool

- **`tek_kullanimlik/anilist_airing_backfill.php` updated for 1.1.10.** In 1.1.9
  it folded everything into a single "not-finished -> ongoing" bucket; it now
  asks AniList for every animes.mal_id and emits a SEPARATE UPDATE per target
  state (same mapping as anilist_airing_status_to_enum): NOT_YET_RELEASED ->
  Not Yet Aired, CANCELLED -> Cancelled, RELEASING/HIATUS -> Ongoing, FINISHED
  -> Finished. A row is written only when the target differs from its current
  status. Rows where AniList returns a duplicate/inconsistent idMal go to a
  manual-review list (never touched automatically). The "-> Finished" block is
  emitted commented out (a raw flip does not reconcile aired/total the way the
  edit form does). Same pacing/retry/resume design is preserved.

## Central catalog note (IMPORTANT)

- The central catalog server (`catalog_server/`) does NOT run the
  MigrationManager. Its `animes.status` enum must be ALTERed by hand to the same
  five values, otherwise a pushed row carrying a new status is rejected:
 
  ```sql
  ALTER TABLE `animes`
    MODIFY `status` enum('Yayın Tamamlandı','Yayın Devam Ediyor',
      'Yayın Başlamadı','Seçim Yapılmadı','Yayın İptal Edildi') NOT NULL;
  ```
 

## Changed files

- schema.sql (animes.status + catalog_requests.status enums)
- migration/1.1.10/upgrade.sql (new - ALTERs both tables)
- functions/broadcast_status_helpers.php (new helper)
- functions.php (loads the new helper)
- functions/anilist_import_helpers.php (five-state mapping)
- functions/animeschedule_helpers.php (Upcoming mapping + Not-Yet sweep/promote)
- sync_aired.php (started counter in cron summary)
- add_anime.php, edit_anime.php (status dropdown + server-side normalization)
- index.php (filter dropdown)
- recent.php, statistics.php, anime_details.php, pending.php,
  admin/admin_pending.php, admin/admin_catalog_requests.php (label helper)
- list_settings.php (whitelist + defaults + web sync started counter)
- catalog_import.php, catalog_server/admin_push.php (default status)
- lang/tr.php, lang/en.php (three new label keys + started result label)
- tek_kullanimlik/anilist_airing_backfill.php (four-state backfill)
- version.txt

GitHub Download
#79
Announcements & Releases / v1.1.9
Last post by hitsumo - Jul 14, 2026, 08:33 AM
Anime Tracker 1.1.9

Release date:** 2026-07-13

 Improvement

- **Language-aware "no image" placeholder for posterless animes.** Animes with
  no poster used to render a broken image on the list and detail pages; they now
  show a "no image" placeholder that matches the interface language. When you
  switch the interface language the placeholder switches too: "BURADA RESIM YOK"
  in Turkish, "IMAGE NOT HERE" in English.

  - As soon as you add a real poster to an anime, the placeholder disappears on
    its own (the real poster is shown).
  - Every place a poster is shown is covered: list, anime detail, recently
    added, recommendations, series timeline, and pending.

 How it works (technical)

- The placeholder is NOT written to the database; while image_path is empty it
  is chosen at display time by language (new `poster_src()` helper). So there
  are NO per-anime file copies and NO database writes - just two static images.
- Dual-mode: on a catalog client, a posterless anime shows the placeholder in
  ITS OWN language (the placeholder is never sent over the catalog wire).

 Setup note

- Place the two images under `img/` with these names:
  - `img/no_poster_tr.png` (Turkish - "BURADA RESIM YOK")
  - `img/no_poster_en.png` (English - "IMAGE NOT HERE")

 Fix

- **Poster proportions on the detail page.** The cover area on the anime detail
  page stretched portrait posters into a landscape box, making them look
  squashed (an invalid `object-fit` value). Posters now display at their correct
  aspect ratio (the cover box was made portrait: 400x600). This applies to the
  new "no image" placeholder too - it also shows at the correct ratio.

 Notes

- No schema change in this release (code plus two images only).

Maintenance / housekeeping

- One-time CLI tools were gathered under `files/tek_kullanimlik/`
  (anilist_isadult_backfill.php was moved there) so they do not mix with the
  main files.

- New maintenance tool: `tek_kullanimlik/anilist_airing_backfill.php` - finds
  animes recorded as "finished" in the catalog that AniList still reports as
  airing/upcoming and emits UPDATE SQL (catalog rows added without airing info
  default to "finished"). Modeled on the isAdult backfill; does not touch the DB.

Changed files

- functions/anime_helpers.php (new poster_src() helper)
- index.php, anime_details.php, recent.php, recommendations.php,
  series_timeline.php, pending.php (poster renders via poster_src)
- css/base.css (.anime-cover object-fit fix + portrait box)
- img/no_poster_tr.png, img/no_poster_en.png (new images)
- tek_kullanimlik/anilist_isadult_backfill.php (moved here)
- version.txt
- migration/1.1.9/upgrade.sql (new, no-op)

Download Github
#80
Announcements & Releases / v1.1.8
Last post by hitsumo - Jul 13, 2026, 07:38 AM
Anime Tracker 1.1.8

Release date:** 2026-07-12

Improvement

- **Saving an anime is now much faster.** When you add or edit an anime, the
  app used to resend the ENTIRE catalog to the central server; as the catalog
  grew (thousands of animes) this made saving wait on a full resync. Now only
  the relevant anime's **series** (rows sharing the same series name) is sent,
  or just that one anime when it has no series name. So saving pushes a handful
  of records instead of the whole catalog.

## For administrators

- **"Push Entire Catalog" button on the edit page (admin only).** Since the
  normal "Update" now sends only the relevant series, an admin who wants to
  resend the whole catalog to the server at once uses this button. (The
  existing manual push tool only worked on localhost; this button works online.)
 Notes

- No schema change in this release.
- Bulk approval (promoting pending items) and adding a chronology note still
 Interface

- List/detail buttons ("Anime List", "Anime Details", etc.) changed from blue
  to teal.

 Changed files

- admin/catalog_push.php
- edit_anime.php
- add_anime.php
- lang/tr.php, lang/en.php
- css/list.css
- version.txt
- migration/1.1.8/upgrade.sql (new, no-op)

Download Github