     case close
   }
 
-  @objc dynamic var unsortedScoredUrls = [ScoredUrl]()
+  @objc dynamic private(set) var unsortedScoredUrls = [ScoredUrl]()
 
   required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
     self.emit = emitter.typedEmit()
     self.windowController = NSWindowController(windowNibName: NSNib.Name("OpenQuicklyWindow"))
 
-    self.searchStream = self.searchField.rx
-      .text.orEmpty
-      .throttle(.milliseconds(2 * 500), latest: true, scheduler: MainScheduler.instance)
-      .distinctUntilChanged()
-
     super.init()
 
     self.window.delegate = self
-
     self.addViews()
 
     source
       .observeOn(MainScheduler.instance)
-      .subscribe(onNext: { state in
-        self.updateRootUrls(state: state)
-
-        guard state.openQuickly.open else {
-          self.windowController.close()
-          return
-        }
-
-        if self.window.isKeyWindow {
-          // already open, so do nothing
-          return
-        }
-
-        self.cwd = state.openQuickly.cwd
-        self.cwdPathCompsCount = self.cwd.pathComponents.count
-        self.cwdControl.url = self.cwd
-
-        self.searchStream
-          .observeOn(MainScheduler.instance)
-          .subscribe(onNext: { [weak self] pattern in self?.scanAndScore(pattern) })
-          .disposed(by: self.disposeBag)
-
-        self.windowController.showWindow(self)
-      })
+      .subscribe(onNext: { [weak self] state in self?.subscription(state) })
       .disposed(by: self.disposeBag)
   }
 

    let truncatedPathComps = pathComps[self.cwdPathCompsCount..<pathComps.count]
    let name = truncatedPathComps.last!

    if truncatedPathComps.dropLast().isEmpty {
      return NSMutableAttributedString(string: name)
    }

    let rowText: NSMutableAttributedString
    let pathInfo = truncatedPathComps.dropLast().reversed().joined(separator: " / ")

    self.searchField.stringValue = ""
  }

  func windowDidResignKey(_: Notification) { self.window.performClose(self) }
}
