narou 2.6.1 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of narou might be problematic. Click here for more details.

Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +65 -0
  3. data/README.md +69 -22
  4. data/lib/command.rb +1 -0
  5. data/lib/command/alias.rb +2 -2
  6. data/lib/command/convert.rb +3 -3
  7. data/lib/command/csv.rb +108 -0
  8. data/lib/command/download.rb +13 -1
  9. data/lib/command/freeze.rb +1 -1
  10. data/lib/command/init.rb +5 -1
  11. data/lib/command/inspect.rb +1 -1
  12. data/lib/command/mail.rb +1 -1
  13. data/lib/command/send.rb +2 -2
  14. data/lib/command/setting.rb +17 -1
  15. data/lib/command/tag.rb +28 -9
  16. data/lib/command/update.rb +57 -30
  17. data/lib/commandbase.rb +3 -2
  18. data/lib/commandline.rb +2 -2
  19. data/lib/converterbase.rb +70 -7
  20. data/lib/database.rb +1 -1
  21. data/lib/device.rb +3 -0
  22. data/lib/device/ibooks.rb +2 -2
  23. data/lib/device/ibunko.rb +4 -0
  24. data/lib/diffviewer.rb +2 -2
  25. data/lib/downloader.rb +16 -9
  26. data/lib/helper.rb +53 -22
  27. data/lib/inventory.rb +6 -2
  28. data/lib/narou.rb +13 -6
  29. data/lib/novelconverter.rb +35 -13
  30. data/lib/novelsetting.rb +7 -1
  31. data/lib/version.rb +1 -1
  32. data/lib/web/appserver.rb +78 -8
  33. data/lib/web/public/resources/common.ui.js +0 -39
  34. data/lib/web/public/resources/dataTables.colVis.js +1 -1
  35. data/lib/web/public/resources/default-style.css +1 -1
  36. data/lib/web/public/resources/help/bookmarklet1.png +0 -0
  37. data/lib/web/public/resources/help/bookmarklet2.png +0 -0
  38. data/lib/web/public/resources/images/dl_button0.gif +0 -0
  39. data/lib/web/public/resources/images/dl_button1.gif +0 -0
  40. data/lib/web/public/resources/narou.library.js +268 -36
  41. data/lib/web/public/resources/narou.queue.js +51 -0
  42. data/lib/web/public/resources/narou.ui.js +156 -59
  43. data/lib/web/settingmessages.rb +2 -1
  44. data/lib/web/views/{js/widget.erb → bookmarklet/download.js.erb} +1 -1
  45. data/lib/web/views/bookmarklet/insert_button.js.erb +133 -0
  46. data/lib/web/views/help.haml +31 -14
  47. data/lib/web/views/index.haml +62 -0
  48. data/lib/web/views/layout.haml +8 -7
  49. data/lib/web/views/parts/csv_import.haml +68 -0
  50. data/lib/web/views/parts/download_form.haml +89 -0
  51. data/lib/web/views/settings.haml +8 -3
  52. data/lib/web/views/style.scss +200 -14
  53. data/lib/web/views/{widget.haml → widget/download.haml} +18 -4
  54. data/lib/web/views/widget/drag_and_drop.haml +97 -0
  55. data/lib/web/worker.rb +39 -1
  56. data/narou.gemspec +56 -56
  57. data/preset/custom_chuki_tag.txt +1 -1
  58. data/preset/doubledash.png +0 -0
  59. data/preset/singledash.png +0 -0
  60. data/preset/vertical_font.css +1 -1
  61. data/spec/convert_spec.rb +5 -1
  62. data/spec/data/convert_test/auto_join_line/correct_test_auto_join_line.txt +6 -0
  63. data/spec/data/convert_test/auto_join_line/test_auto_join_line.txt +8 -0
  64. data/spec/data/convert_test/double_dash_to_image/correct_test_double_dash_to_image.txt +14 -0
  65. data/spec/data/convert_test/double_dash_to_image/setting.ini +1 -0
  66. data/spec/data/convert_test/double_dash_to_image/test_double_dash_to_image.txt +12 -0
  67. data/spec/worker_spec.rb +21 -2
  68. metadata +97 -60
@@ -0,0 +1,51 @@
1
+ /* -*- coding: utf-8 -*-
2
+ *
3
+ * Copyright 2013 whiteleaf. All rights reserved.
4
+ */
5
+
6
+ /*
7
+ * キュー関係のコード
8
+ */
9
+ $(document).ready(function() {
10
+ "use strict";
11
+
12
+ /*
13
+ * キューに積まれた数を表示
14
+ */
15
+ var notification = Narou.Notification.instance();
16
+ var $queue = $("#queue");
17
+ function highlightQueuBoxIcon(size) {
18
+ if (size > 0) {
19
+ $("#queue-text").addClass("active");
20
+ }
21
+ else {
22
+ $("#queue-text").removeClass("active");
23
+ }
24
+ }
25
+ notification.on("notification.queue", function(data) {
26
+ var before_size = $queue.text();
27
+ $queue.text(data);
28
+ highlightQueuBoxIcon(data);
29
+ // キューのスタック数の横に +1 が浮かび上がって消えるアニメーション
30
+ var diff = data - before_size;
31
+ if (diff <= 0) return;
32
+ var $plus = $("<span>+" + diff + "</span>");
33
+ $plus.addClass("queue-plus").css({
34
+ position: "absolute",
35
+ left: $queue.offset().left + $queue.outerWidth() + 1 - $(document).scrollLeft(),
36
+ top: $queue.offset().top - 3 - $(document).scrollTop(),
37
+ });
38
+ $(".navbar").append($plus);
39
+ $plus.delay(100).animate({
40
+ top: - $plus.outerHeight(),
41
+ opacity: 0,
42
+ }, 3000, function() {
43
+ $(this).remove();
44
+ });
45
+ });
46
+ $.get("/api/get_queue_size", function(json) {
47
+ $queue.text(json.size);
48
+ highlightQueuBoxIcon(json.size);
49
+ });
50
+ });
51
+
@@ -20,7 +20,7 @@ $(document).ready(function() {
20
20
  {
21
21
  id: false, last_update: false, title: true, author: false, sitename: false,
22
22
  toc_url: false, novel_type: false, tags: false, status: false, menu: true,
23
- download: false, folder: false, general_lastup: false,
23
+ download: true, folder: false, general_lastup: false,
24
24
  }
25
25
  // PC
26
26
  : {
@@ -71,6 +71,20 @@ $(document).ready(function() {
71
71
  return Narou.formatDate(dateobj, "YYYYMMDD") === today();
72
72
  }
73
73
 
74
+ // initComplete や ajax.reload した時に再設定するために呼ばれる
75
+ function resettingTableState() {
76
+ table.$("[data-toggle=tooltip]").tooltip({
77
+ animation: false,
78
+ container: "body",
79
+ });
80
+ // バッジを更新しておく(.selectedの復元が終わってから呼ぶ)
81
+ table.fireChangeSelect();
82
+ // タグのイベントを反映
83
+ tag.registerEvents(table);
84
+
85
+ table.draw(false);
86
+ }
87
+
74
88
  var table = t = $("#novel-list").DataTable({
75
89
  ajax: "/api/list",
76
90
  dom: (touchable_device ? 'lprtpi' : 'Rlprtpi'),
@@ -248,29 +262,31 @@ $(document).ready(function() {
248
262
  }
249
263
  },
250
264
  initComplete: function(_settings, _json) {
251
- table.$("[data-toggle=tooltip]").tooltip({
252
- animation: false,
253
- container: "body",
254
- });
255
- // バッジを更新しておく
256
- table.fireChangeSelect();
265
+ // タグ検索を復元
266
+ $tag_search.val(storage.get("tag_search"));
257
267
  // 範囲選択モードでもリンクとボタンが使えるように
258
- table.$("a, button").on("mousedown", function(e) {
268
+ table.on("mousedown", "a, button", function(e) {
259
269
  e.stopPropagation();
260
270
  });
261
- // タグのイベントを反映
262
- tag.registerEvents(table);
263
- // タグ検索を復元
264
- $tag_search.val(storage.get("tag_search"));
271
+ // リンククリックした時点でツールチップは消す
272
+ table.on("click", "a", function(e) {
273
+ $(this).tooltip("hide");
274
+ });
275
+ resettingTableState();
276
+
265
277
  table.draw(false);
266
278
  },
267
279
  language: {
268
280
  //lengthMenu: "_MENU_ 件分表示 <span id='icon-refresh-table' class='glyphicon glyphicon-repeat'></span>",
269
281
  lengthMenu: "_MENU_ 件分表示",
270
- zeroRecords: "データがひとつもないか、処理中です",
282
+ emptyTable: "データが登録されていません",
283
+ zeroRecords: "ひとつも見つかりませんでした",
284
+ infoPostFix: "",
271
285
  info: "Page _PAGE_ of _PAGES_",
272
286
  infoEmpty: "該当なし",
273
287
  infoFiltered: "(全_MAX_件から検索しました)",
288
+ loadingRecords: "ロード中です",
289
+ processing: "処理中...",
274
290
  paginate: {
275
291
  first: "&laquo;",
276
292
  previous: "前へ",
@@ -292,6 +308,7 @@ $(document).ready(function() {
292
308
  var stream_console = new Narou.Console(notification);
293
309
  var tag = new Narou.Tag(table);
294
310
  var context_menu = new Narou.ContextMenu(action, notification, tag);
311
+ var select_color_menu = new Narou.SelectColorMenu;
295
312
 
296
313
  /*
297
314
  * 凍結の表示状態制御
@@ -351,17 +368,12 @@ $(document).ready(function() {
351
368
  });
352
369
  table.ajax.reload(function() {
353
370
  // リロードしたら状態は解除されているので復元
354
- table.$("[data-toggle=tooltip]").tooltip({
355
- animation: false,
356
- container: "body",
357
- });
358
371
  table.eachRow(function(row, data) {
359
372
  if ($.inArray(data.id, selected_ids) !== -1) {
360
373
  $(row.node()).addClass("selected");
361
374
  }
362
375
  });
363
- table.fireChangeSelect();
364
- table.draw(false);
376
+ resettingTableState();
365
377
  }, false);
366
378
  });
367
379
 
@@ -369,8 +381,6 @@ $(document).ready(function() {
369
381
  tag.updateCanvas();
370
382
  });
371
383
 
372
- tag.registerEvents($(".tag-field"));
373
-
374
384
  var action_select_view = $("#action-select-view");
375
385
  var myfilter_clear = $("#myFilter-clear");
376
386
 
@@ -432,23 +442,17 @@ $(document).ready(function() {
432
442
  };
433
443
 
434
444
  function get_event_position(e) {
435
- if (e.type !== "touchstart") {
436
- return { x: e.pageX, y: e.pageY };
437
- }
438
- else {
439
- return { x: e.originalEvent.touches[0].pageX,
440
- y: e.originalEvent.touches[0].pageY };
441
- }
445
+ return Narou.get_event_position(e);
442
446
  }
443
447
 
444
- var select_mode = storage.get("select_mode") || "single";
448
+ var select_mode = storage.get("select_mode") || "hybrid";
445
449
  var enable_rect_select_mode = function() {};
446
450
  var disable_rect_select_mode = function() {};
447
451
 
448
452
  $("#action-select-mode-single").on(click_event_name, function(e) {
449
453
  if (select_mode != "single") {
450
454
  $(this).addClass("active");
451
- $("#action-select-mode-rect").removeClass("active");
455
+ $("#action-select-mode-" + select_mode).removeClass("active");
452
456
  select_mode = "single";
453
457
  storage.set("select_mode", select_mode).save();
454
458
  disable_rect_select_mode();
@@ -485,15 +489,27 @@ $(document).ready(function() {
485
489
  $("#action-select-mode-rect").addClass("disabled");
486
490
  }
487
491
  else {
488
- $("#action-select-mode-rect").on(click_event_name, function(e) {
489
- if (select_mode != "rect") {
490
- $(this).addClass("active");
491
- $("#action-select-mode-single").removeClass("active");
492
- select_mode = "rect";
493
- storage.set("select_mode", select_mode).save();
494
- disable_single_select_mode();
495
- enable_rect_select_mode();
492
+ var initMode = function(mode) {
493
+ if (select_mode != mode) {
494
+ $("#action-select-mode-" + mode).addClass("active");
495
+ $("#action-select-mode-" + select_mode).removeClass("active");
496
+ if (select_mode == "single") {
497
+ disable_single_select_mode();
498
+ enable_rect_select_mode();
499
+ }
500
+ select_mode = mode;
501
+ storage.set("select_mode", mode).save();
502
+ $("#novel-list tbody, #rect-select-area")
503
+ .css("cursor", mode == "rect" ? "crosshair" : "pointer");
496
504
  }
505
+ };
506
+ $("#action-select-mode-rect").on(click_event_name, function(e) {
507
+ initMode("rect");
508
+ slideNavbar.close();
509
+ e.preventDefault();
510
+ });
511
+ $("#action-select-mode-hybrid").on(click_event_name, function(e) {
512
+ initMode("hybrid");
497
513
  slideNavbar.close();
498
514
  e.preventDefault();
499
515
  });
@@ -557,6 +573,7 @@ $(document).ready(function() {
557
573
  table.fireChangeSelect();
558
574
  menu.hide();
559
575
  selected_rect_element.hide();
576
+ $(this).children("a").blur();
560
577
  });
561
578
  // 解除
562
579
  $("#rect-select-menu-clear").on("click", function(e) {
@@ -568,6 +585,7 @@ $(document).ready(function() {
568
585
  table.fireChangeSelect();
569
586
  menu.hide();
570
587
  selected_rect_element.hide();
588
+ $(this).children("a").blur();
571
589
  });
572
590
  // 反転
573
591
  $("#rect-select-menu-reverse").on("click", function(e) {
@@ -579,12 +597,15 @@ $(document).ready(function() {
579
597
  table.fireChangeSelect();
580
598
  menu.hide();
581
599
  selected_rect_element.hide();
600
+ $(this).children("a").blur();
582
601
  });
583
602
  // キャンセル
584
603
  $("#rect-select-menu-cancel").on("click", function(e) {
585
604
  e.preventDefault();
605
+ e.stopPropagation();
586
606
  menu.hide();
587
607
  selected_rect_element.hide();
608
+ $(this).children("a").blur();
588
609
  });
589
610
  };
590
611
  rect_select_menu_initialize();
@@ -594,7 +615,11 @@ $(document).ready(function() {
594
615
  var is_moved = false;
595
616
  var start_position = null;
596
617
  var end_position = null;
597
- $("#novel-list tbody, #rect-select-area").css("cursor", "crosshair");
618
+ var resetCursor = function() {
619
+ $("#novel-list tbody, #rect-select-area")
620
+ .css("cursor", select_mode == "rect" ? "crosshair" : "pointer");
621
+ };
622
+ resetCursor();
598
623
  $("body").on("mousedown", function(e) {
599
624
  var _pos = get_event_position(e);
600
625
  var mousedowned_element = $.elementFromPoint(_pos);
@@ -603,11 +628,22 @@ $(document).ready(function() {
603
628
  e.preventDefault();
604
629
  e.stopPropagation();
605
630
  var self = this;
631
+ var moving_count = 0;
606
632
  var finish_selecting_proc = function() {
607
633
  $(self).off("mousemove mouseup");
608
634
  not_clicked_yet = true;
609
635
  is_moved = false;
610
636
  Narou.popupMenu("#rect-select-menu", end_position, close_rect_select_menu_handler);
637
+ resetCursor();
638
+ };
639
+ var mouse_up_when_mode_hybrid_proc = function() {
640
+ mousedowned_element.parents("tr").toggleClass("selected");
641
+ $(self).off("mousemove mouseup");
642
+ not_clicked_yet = true;
643
+ is_moved = false;
644
+ table.fireChangeSelect();
645
+ $("#rect-select-menu").hide();
646
+ selected_rect_element.hide();
611
647
  };
612
648
  if (not_clicked_yet) {
613
649
  // 範囲選択開始
@@ -617,7 +653,14 @@ $(document).ready(function() {
617
653
  start_position = _pos;
618
654
  start_element = mousedowned_element;
619
655
  $(self).on("mousemove", function(e) {
656
+ moving_count++;
657
+ if (select_mode == "hybrid" && moving_count < 10) {
658
+ // 範囲選択化への遊び。多少動かした程度はクリックとみなす
659
+ return;
660
+ }
620
661
  is_moved = true;
662
+ selected_rect_element.show();
663
+ $("#novel-list tbody, #rect-select-area").css("cursor", "crosshair");
621
664
  var pos = get_event_position(e);
622
665
  if ($.elementFromPoint(pos).closest("#novel-list tbody").length === 0)
623
666
  return;
@@ -638,12 +681,15 @@ $(document).ready(function() {
638
681
  if (is_moved) {
639
682
  finish_selecting_proc();
640
683
  }
684
+ else if (select_mode == "hybrid") {
685
+ mouse_up_when_mode_hybrid_proc();
686
+ }
641
687
  });
642
688
  selected_rect_element.css({
643
689
  left: start_position.x,
644
690
  top: start_position.y,
645
691
  width: 1, height: 1
646
- }).show();
692
+ });
647
693
  }
648
694
  else {
649
695
  finish_selecting_proc();
@@ -653,14 +699,11 @@ $(document).ready(function() {
653
699
  }
654
700
 
655
701
  function restore_select_mode() {
656
- if (select_mode === "single") {
702
+ if (select_mode === "single")
657
703
  enable_single_select_mode();
658
- $("#action-select-mode-single").addClass("active");
659
- }
660
- else {
704
+ else
661
705
  enable_rect_select_mode();
662
- $("#action-select-mode-rect").addClass("active");
663
- }
706
+ $("#action-select-mode-" + select_mode).addClass("active");
664
707
  }
665
708
  restore_select_mode();
666
709
 
@@ -786,6 +829,37 @@ $(document).ready(function() {
786
829
  tag.openEditor();
787
830
  });
788
831
 
832
+ /*
833
+ * メニュー
834
+ * ツール > D&Dウィンドウを開く
835
+ */
836
+ $("#action-tool-open-dnd-window").on(click_event_name, function(e) {
837
+ e.preventDefault();
838
+ slideNavbar.slide();
839
+ window.open("/widget/drag_and_drop", "widget_window",
840
+ "width=400,height=350,menubar=no,toolbar=no,scrollbars=no,resizable=yes");
841
+ });
842
+
843
+ /*
844
+ * メニュー
845
+ * ツール > CSV形式でリストをダウンロード
846
+ */
847
+ $("#action-tool-csv-download").on(click_event_name, function(e) {
848
+ e.preventDefault();
849
+ slideNavbar.slide();
850
+ location.href = "/api/csv/download"
851
+ });
852
+
853
+ /*
854
+ * メニュー
855
+ * ツール > CSVファイルからインポート
856
+ */
857
+ $("#action-tool-csv-import").on(click_event_name, function(e) {
858
+ e.preventDefault();
859
+ slideNavbar.slide();
860
+ action.csvImport();
861
+ });
862
+
789
863
  /*
790
864
  * メニュー
791
865
  * オプション>環境設定
@@ -895,14 +969,20 @@ $(document).ready(function() {
895
969
  container: "body",
896
970
  });
897
971
 
972
+ $("button").on("mouseleave", function() {
973
+ $(this).tooltip("hide");
974
+ });
975
+
898
976
  /*
899
977
  * ボタンを一時的に非アクティブ化
900
978
  */
901
979
  function disableButtonMoment($button) {
902
- $button.addClass("disabled");
980
+ $button.blur();
981
+ $button.tooltip("hide");
982
+ $button.prop("disabled", true);
903
983
  // 少したったらアクティブに戻す
904
984
  setTimeout(function() {
905
- $button.removeClass("disabled");
985
+ $button.prop("disabled", false);
906
986
  }, 1000);
907
987
  }
908
988
 
@@ -971,6 +1051,15 @@ $(document).ready(function() {
971
1051
  action.send();
972
1052
  });
973
1053
 
1054
+ /*
1055
+ * ボタン
1056
+ * Send > hotnentry を送信
1057
+ */
1058
+ $("#button-send-hotentry").on("click", function(e) {
1059
+ e.preventDefault();
1060
+ action.send("hotentry");
1061
+ });
1062
+
974
1063
  /*
975
1064
  * ボタン
976
1065
  * Freeze > 選択した小説を凍結
@@ -1102,12 +1191,9 @@ $(document).ready(function() {
1102
1191
  action.selectClear();
1103
1192
  }
1104
1193
  });
1105
- add("S", function() {
1106
- $("#action-select-mode-single").trigger("click");
1107
- });
1108
- add("R", function() {
1109
- $("#action-select-mode-rect").trigger("click");
1110
- });
1194
+ add("S", function() { $("#action-select-mode-single").trigger("click"); });
1195
+ add("R", function() { $("#action-select-mode-rect").trigger("click"); });
1196
+ add("H", function() { $("#action-select-mode-hybrid").trigger("click"); });
1111
1197
  };
1112
1198
  if (!touchable_device) {
1113
1199
  initialize_shortcut();
@@ -1116,13 +1202,24 @@ $(document).ready(function() {
1116
1202
  /*
1117
1203
  * disabled なメニューは何もしないように
1118
1204
  */
1119
- var nothing_to_do = function() { return false };
1120
- function disable_menu_item(id) {
1121
- $(id).addClass("disabled").on(click_event_name, nothing_to_do);
1205
+ function disable_menu_item(selector) {
1206
+ var $element = $(selector);
1207
+ $element.each(function(i, dom) {
1208
+ if (dom.tagName.toLowerCase() == "button")
1209
+ $(dom).prop("disabled", true);
1210
+ else
1211
+ $(dom).addClass("disabled");
1212
+ });
1122
1213
  }
1123
1214
 
1124
- function enable_menu_item(id) {
1125
- $(id).removeClass("disabled").off(click_event_name, nothing_to_do);
1215
+ function enable_menu_item(selector) {
1216
+ var $element = $(selector);
1217
+ $element.each(function(i, dom) {
1218
+ if (dom.tagName.toLowerCase() == "button")
1219
+ $(dom).prop("disabled", false);
1220
+ else
1221
+ $(dom).removeClass("disabled");
1222
+ });
1126
1223
  }
1127
1224
 
1128
1225
  disable_menu_item(".navbar li.disabled");