 (register-handler
   :seasons-load-error
   (fn [db [_ error]]
-    (print error)
+    (if (= (.-message err) "Network request failed")
+      (dispatch [:show-network-error])
+      (print err))
     db))
 
-(register-handler
-  :resort-chapter
-  (fn [db [_ sort-type]]
-    (assoc db :sort-chapter sort-type)))
+(defn load-chapters-content [content active-content remote-db chapters-path]
+  (-> (load-if-not-exist
+       (partial get-chapters-by-index content active-content)
+       (partial rdb/download-json remote-db chapters-path)
+       (fn [chapters]
+         (dispatch [:chapters-load-success chapters])))
+      (.catch
+       (fn [err]
+         (dispatch [:chapters-load-error err])))))
+
+(register-handler
+  :chapters-load
+  (fn [{:keys [content active-content remote-db] :as db}
+       [_ {id :id chapters-path :path}]]
+    (let [new-active-content (set-active-season id active-content)]
+      (api-proxy
+       (partial load-chapters-content
+                content
+                active-content
+                remote-db
+                chapters-path))
+      (-> db
+          (assoc :active-content new-active-content)))))
+
+(register-handler
+  :chapters-load-success
+  (fn [{:keys [content active-content] :as db} [_ chapters]]
+    (-> db
+        (assoc :content (update-chapters
+                         content
+                         active-content
+                         #(parse-chapters chapters))))))
+
+(register-handler
+  :chapters-load-error
+  (fn [db [_ error]]
+    (if (= (.-message err) "Network request failed")
+      (dispatch [:show-network-error])
+      (print err))
+    db))
+
+(defn load-srt-content [content active-content remote-db srt-path]
+  (-> (load-if-not-exist
+       (partial get-chapter-by-index content active-content)
+       (partial rdb/download remote-db srt-path)
+       (fn [srt]
+         (dispatch [:srt-load-success srt])))
+      (.catch
+       (fn [err]
+         (dispatch [:srt-load-error err])))))
+
+(register-handler
+  :chapter-load
+  (fn [{:keys [content active-content remote-db] :as db}
+       [_ {id :id srt-path :path}]]
+    (let [new-active-content (set-active-chapter id active-content)]
+      (api-proxy
+       (partial load-srt-content
+                content
+                active-content
+                remote-db
+                srt-path))
+      (-> db
+          (assoc :active-content new-active-content)))))
+
+(register-handler
+  :srt-load-success
+  (fn [{:keys [content active-content] :as db} [_ chapter]]
+    (-> db
+        (assoc :content (update-chapter
+                         content
+                         active-content
+                         #(parse-srt chapter))))))
+
+(register-handler
+  :srt-load-error
+  (fn [db [_ error]]
+    (if (= (.-message err) "Network request failed")
+      (dispatch [:show-network-error])
+      (print err))
+    db))
+
+;; ------ Translate -------
+;; TODO: need to cache translations
 
 (register-handler
   :translate-term

   (fn [chapters]
     (-> chapters
         (update (-> index (rest) (rest) (first)) updater)))))

(defn load-if-not-exist
  ([getter load-fn on-loaded]

(defn set-active-serial [serial-id active-content-index]
  (assoc active-content-index 0 serial-id))

(defn set-active-season [season-id active-content-index]
  (assoc active-content-index 1 season-id))

(defn set-active-chapter [chapter-id active-content-index]
  (assoc active-content-index 2 chapter-id))

;; TODO: think about lenses

(defn save-apply [& args]
