kamishibai 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/LICENSE +29 -0
  4. data/README.md +91 -0
  5. data/bin/kamishibai +59 -0
  6. data/changelogs.txt +6 -0
  7. data/images/reading.jpg +0 -0
  8. data/images/settings.jpg +0 -0
  9. data/images/view_browse.jpg +0 -0
  10. data/images/view_dir.jpg +0 -0
  11. data/kamishibai.gemspec +31 -0
  12. data/lib/kamishibai.rb +35 -0
  13. data/lib/kamishibai/book.rb +97 -0
  14. data/lib/kamishibai/config.rb +90 -0
  15. data/lib/kamishibai/database.rb +330 -0
  16. data/lib/kamishibai/functions.rb +332 -0
  17. data/lib/kamishibai/patches.rb +58 -0
  18. data/lib/kamishibai/version.rb +7 -0
  19. data/lib/kamishibai/webserver.rb +502 -0
  20. data/lib/kamishibai/webserver_cmds.rb +26 -0
  21. data/lib/kamishibai/webserver_config.rb +91 -0
  22. data/lib/kamishibai/webserver_filemanager.rb +29 -0
  23. data/lib/kamishibai/webserver_tablet.rb +259 -0
  24. data/lib/kamishibai/workers.rb +39 -0
  25. data/public/css/browse.css +390 -0
  26. data/public/css/config.css +3 -0
  27. data/public/css/reader.css +119 -0
  28. data/public/css/styles.css +30 -0
  29. data/public/css/tablet_browse.css +247 -0
  30. data/public/css/tablet_reader.css +323 -0
  31. data/public/css/tablet_reader_input.css +191 -0
  32. data/public/images/ajax-loader.gif +0 -0
  33. data/public/images/delete.png +0 -0
  34. data/public/images/folder-mini-up.png +0 -0
  35. data/public/images/folder-mini.png +0 -0
  36. data/public/images/spinner.gif +0 -0
  37. data/public/images/trash-empty-mini.png +0 -0
  38. data/public/images/trash-full-mini.png +0 -0
  39. data/public/js/browse.js +391 -0
  40. data/public/js/config.js +190 -0
  41. data/public/js/reader.js +497 -0
  42. data/public/js/swipeview-k.js +478 -0
  43. data/public/js/tablet3.js +241 -0
  44. data/public/js/tablet3_browse.js +173 -0
  45. data/public/js/tablet3_reader.js +534 -0
  46. data/public/js/utilities.js +170 -0
  47. data/public/lang/k-cn.json +82 -0
  48. data/public/lang/k-en.json +82 -0
  49. data/public/lang/k-ja.json +82 -0
  50. data/public/vendor/css/bootstrap-slider.css +252 -0
  51. data/public/vendor/css/bootstrap-theme.css +476 -0
  52. data/public/vendor/css/bootstrap-theme.css.map +1 -0
  53. data/public/vendor/css/bootstrap-theme.min.css +5 -0
  54. data/public/vendor/css/bootstrap.css +6584 -0
  55. data/public/vendor/css/bootstrap.css.map +1 -0
  56. data/public/vendor/css/bootstrap.min.css +5 -0
  57. data/public/vendor/css/jquery-ui-1.10.0.custom.css +1614 -0
  58. data/public/vendor/css/jquery.mobile-1.3.1.min.css +3 -0
  59. data/public/vendor/css/jqueryFileTree.css +91 -0
  60. data/public/vendor/fonts/glyphicons-halflings-regular.eot +0 -0
  61. data/public/vendor/fonts/glyphicons-halflings-regular.svg +288 -0
  62. data/public/vendor/fonts/glyphicons-halflings-regular.ttf +0 -0
  63. data/public/vendor/fonts/glyphicons-halflings-regular.woff +0 -0
  64. data/public/vendor/fonts/glyphicons-halflings-regular.woff2 +0 -0
  65. data/public/vendor/images/application.png +0 -0
  66. data/public/vendor/images/code.png +0 -0
  67. data/public/vendor/images/css.png +0 -0
  68. data/public/vendor/images/db.png +0 -0
  69. data/public/vendor/images/dim.png +0 -0
  70. data/public/vendor/images/directory.png +0 -0
  71. data/public/vendor/images/doc.png +0 -0
  72. data/public/vendor/images/file.png +0 -0
  73. data/public/vendor/images/film.png +0 -0
  74. data/public/vendor/images/flash.png +0 -0
  75. data/public/vendor/images/folder_open.png +0 -0
  76. data/public/vendor/images/grey.png +0 -0
  77. data/public/vendor/images/html.png +0 -0
  78. data/public/vendor/images/icons-18-black.png +0 -0
  79. data/public/vendor/images/icons-18-white.png +0 -0
  80. data/public/vendor/images/icons-36-black.png +0 -0
  81. data/public/vendor/images/icons-36-white.png +0 -0
  82. data/public/vendor/images/java.png +0 -0
  83. data/public/vendor/images/linux.png +0 -0
  84. data/public/vendor/images/music.png +0 -0
  85. data/public/vendor/images/pdf.png +0 -0
  86. data/public/vendor/images/php.png +0 -0
  87. data/public/vendor/images/picture.png +0 -0
  88. data/public/vendor/images/ppt.png +0 -0
  89. data/public/vendor/images/psd.png +0 -0
  90. data/public/vendor/images/ruby.png +0 -0
  91. data/public/vendor/images/script.png +0 -0
  92. data/public/vendor/images/spinner.gif +0 -0
  93. data/public/vendor/images/txt.png +0 -0
  94. data/public/vendor/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  95. data/public/vendor/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  96. data/public/vendor/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  97. data/public/vendor/images/ui-bg_flat_10_000000_40x100.png +0 -0
  98. data/public/vendor/images/ui-bg_flat_30_cccccc_40x100.png +0 -0
  99. data/public/vendor/images/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  100. data/public/vendor/images/ui-bg_flat_55_fbec88_40x100.png +0 -0
  101. data/public/vendor/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  102. data/public/vendor/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  103. data/public/vendor/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  104. data/public/vendor/images/ui-bg_glass_20_555555_1x400.png +0 -0
  105. data/public/vendor/images/ui-bg_glass_40_0078a3_1x400.png +0 -0
  106. data/public/vendor/images/ui-bg_glass_40_ffc73d_1x400.png +0 -0
  107. data/public/vendor/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  108. data/public/vendor/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  109. data/public/vendor/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  110. data/public/vendor/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  111. data/public/vendor/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  112. data/public/vendor/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  113. data/public/vendor/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  114. data/public/vendor/images/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
  115. data/public/vendor/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  116. data/public/vendor/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  117. data/public/vendor/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  118. data/public/vendor/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  119. data/public/vendor/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  120. data/public/vendor/images/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
  121. data/public/vendor/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  122. data/public/vendor/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  123. data/public/vendor/images/ui-bg_inset-soft_25_000000_1x100.png +0 -0
  124. data/public/vendor/images/ui-bg_inset-soft_30_f58400_1x100.png +0 -0
  125. data/public/vendor/images/ui-icons_217bc0_256x240.png +0 -0
  126. data/public/vendor/images/ui-icons_222222_256x240.png +0 -0
  127. data/public/vendor/images/ui-icons_228ef1_256x240.png +0 -0
  128. data/public/vendor/images/ui-icons_2e83ff_256x240.png +0 -0
  129. data/public/vendor/images/ui-icons_454545_256x240.png +0 -0
  130. data/public/vendor/images/ui-icons_469bdd_256x240.png +0 -0
  131. data/public/vendor/images/ui-icons_4b8e0b_256x240.png +0 -0
  132. data/public/vendor/images/ui-icons_6da8d5_256x240.png +0 -0
  133. data/public/vendor/images/ui-icons_888888_256x240.png +0 -0
  134. data/public/vendor/images/ui-icons_a83300_256x240.png +0 -0
  135. data/public/vendor/images/ui-icons_cccccc_256x240.png +0 -0
  136. data/public/vendor/images/ui-icons_cd0a0a_256x240.png +0 -0
  137. data/public/vendor/images/ui-icons_d8e7f3_256x240.png +0 -0
  138. data/public/vendor/images/ui-icons_ef8c08_256x240.png +0 -0
  139. data/public/vendor/images/ui-icons_f9bd01_256x240.png +0 -0
  140. data/public/vendor/images/ui-icons_ffd27a_256x240.png +0 -0
  141. data/public/vendor/images/ui-icons_ffffff_256x240.png +0 -0
  142. data/public/vendor/images/xls.png +0 -0
  143. data/public/vendor/images/zip.png +0 -0
  144. data/public/vendor/js/bootstrap-slider.js +1550 -0
  145. data/public/vendor/js/bootstrap.js +2317 -0
  146. data/public/vendor/js/bootstrap.min.js +7 -0
  147. data/public/vendor/js/jquery-2.1.4.js +9210 -0
  148. data/public/vendor/js/jquery-2.1.4.min.js +4 -0
  149. data/public/vendor/js/jquery-2.1.4.min.map +1 -0
  150. data/public/vendor/js/jquery-ui-1.10.2.custom.min.js +7 -0
  151. data/public/vendor/js/jquery.cookie.js +72 -0
  152. data/public/vendor/js/jquery.hammer.min.js +7 -0
  153. data/public/vendor/js/jquery.lazyload.min.js +15 -0
  154. data/public/vendor/js/jquery.localize.js +180 -0
  155. data/public/vendor/js/jquery.mobile-1.3.1.min.js +7 -0
  156. data/public/vendor/js/jquery.scrollTo-1.4.3.1.js +218 -0
  157. data/public/vendor/js/jqueryFileTree.js +95 -0
  158. data/public/vendor/js/swipeview.js +471 -0
  159. data/views/browse.haml +97 -0
  160. data/views/config.haml +115 -0
  161. data/views/layout.haml +12 -0
  162. data/views/login.haml +51 -0
  163. data/views/reader.haml +70 -0
  164. data/views/statistics.haml +108 -0
  165. data/views/tablet3.haml +80 -0
  166. metadata +334 -0
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ # License: refer to LICENSE file
4
+
5
+ module Kamishibai
6
+ class Webserver
7
+
8
+ get '/save_bookmarks' do
9
+ $db.save_bookmarks
10
+ end
11
+
12
+ # restart webserver
13
+ get '/restart' do
14
+ $RERUN = true
15
+ Process.kill("TERM", Process.pid)
16
+ '<html><head><meta http-equiv="refresh" content="5; url=/"></head><body>restarting...</body></html>'
17
+ end
18
+
19
+ # shutdown kamishibai
20
+ get '/shutdown' do
21
+ $RERUN = false
22
+ Process.kill("TERM", Process.pid)
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+
3
+ # License: refer to LICENSE file
4
+
5
+ module Kamishibai
6
+ class Webserver
7
+
8
+ # configuration page, get mode
9
+ get '/config' do
10
+ if request['get']
11
+ case request['get']
12
+ when 'srcs'
13
+ # get list of sources
14
+ content_type :javascript
15
+ $settings.srcs.to_s
16
+ when 'prefs'
17
+ content_type :javascript
18
+
19
+ "g_prefs['port'] = #{ $settings.port };\n" +
20
+ "g_prefs['new_book_days'] = #{ $settings.new_book_days };\n" +
21
+ "g_prefs['user'] = \"#{ $settings.username }\";\n" +
22
+ "g_prefs['pass'] = \"#{ $settings.password }\";\n" +
23
+ "g_prefs['resize'] = #{ $settings.image_resize };\n" +
24
+ "g_prefs['quality'] = #{ $settings.default_image_quality };\n"
25
+
26
+ when 'total_books'
27
+ # get number of books in db
28
+ content_type :javascript
29
+ $db.books.length.to_s
30
+ end
31
+ else
32
+ haml :config, :layout => false
33
+ end
34
+ end
35
+
36
+
37
+ # configuration page, set mode
38
+ post '/config' do
39
+ if request['set']
40
+ case request['set']
41
+ when 'srcs'
42
+ # save book sources
43
+ old_srcs = $settings.srcs.collect { |d|
44
+ if d[-1..-1] == '/'
45
+ d[0..-2]
46
+ else
47
+ d[0..-1]
48
+ end
49
+ }.sort
50
+
51
+ srcs = request['srcs'].split('||||').compact
52
+ srcs = srcs.collect { |d|
53
+ if d[-1..-1] == '/'
54
+ d[0..-2]
55
+ else
56
+ d[0..-1]
57
+ end
58
+ }.sort
59
+ $settings.srcs = srcs
60
+
61
+ $settings.save
62
+
63
+ # srcs has changed, reload the whole kamishibai, to reload the db
64
+ if old_srcs != srcs
65
+ init_database
66
+ end
67
+ when 'prefs'
68
+ # save settings
69
+ r = request
70
+
71
+ old_port = $settings.port
72
+ $settings.port = r['port'].to_i
73
+ $settings.image_resize = r['resize'] == 'on' ? true : false
74
+ $settings.username = r['user']
75
+ $settings.password = r['pass']
76
+ $settings.new_book_days = r['new_book_days'].to_i
77
+ $settings.default_image_quality = r['quality'].to_i
78
+
79
+ $settings.save
80
+
81
+ if $settings.port != old_port
82
+ # restart webserver if port is different from old port
83
+ $RERUN = true
84
+ Process.kill("TERM", Process.pid)
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ # License: refer to LICENSE file
4
+
5
+ module Kamishibai
6
+ class Webserver
7
+
8
+ post '/delete_book' do
9
+ bookcode = request['bookcode'].untaint
10
+
11
+ fp = $db.get_book(bookcode).fullpath
12
+
13
+ trash_dir = File.dirname( fp ) + '/Trash'
14
+
15
+ unless FileTest.directory?( trash_dir )
16
+ unless File.stat( File.dirname(fp) ).writable?
17
+ halt "Error. Directory is read only! #{ File.dirname(fp) }"
18
+ end
19
+
20
+ Dir.mkdir( trash_dir )
21
+ end
22
+
23
+ # "#{fp} ... #{trash_dir}"
24
+ File.rename( fp, trash_dir + '/' + File.basename(fp) )
25
+
26
+ "deleted #{File.basename(fp)}"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,259 @@
1
+ # encoding: utf-8
2
+
3
+ # License: refer to LICENSE file
4
+
5
+ module Kamishibai
6
+ class Webserver
7
+ helpers do
8
+ end
9
+
10
+ # show all unique titles
11
+ post '/lists' do
12
+ content_type :text
13
+
14
+ titles = {}
15
+ $db.books.each { |bookcode, book|
16
+ next unless book.fullpath_valid
17
+ next unless book.title
18
+ next unless pregex.match( book.title )
19
+
20
+ if titles[ book.title ]
21
+ titles[ book.title ] << book.bookcode
22
+ else
23
+ titles[ book.title ] = [ book.bookcode ]
24
+ end
25
+ }
26
+
27
+ # sort by title alphabetically
28
+ titles = titles.sort { |a, b| a[0] <=> b[0] }
29
+
30
+ c = ' ' # double space instead of 0 byte, so book without title or obscure filename can be group and have divider
31
+ html = ''
32
+ titles.each { |title, bookcodes|
33
+ if c != title[0..0]
34
+ # add divider
35
+ c = title[0..0] == '' ? '-' : title[0..0]
36
+ html << "<li class=\"ui-li-divider\">#{c}</li>\n"
37
+ end
38
+
39
+ # html << "<li class=\"li-title\" bookcodes=\"#{bookcodes.join(',')}\">#{title.escape_html}</li>\n"
40
+ html << "<li class=\"li-title\" bookcodes=\"#{bookcodes.join(',')}\">#{title.escape_html}</li>\n"
41
+ }
42
+ html
43
+ end
44
+
45
+ # lists containing newly imported books
46
+ post '/nlists' do
47
+ content_type :text
48
+
49
+ titles = {}
50
+ $db.books.each { |bookcode, book|
51
+ next unless book.fullpath_valid
52
+ next unless book.itime
53
+ next unless Time.now.to_i - book.itime < 3600*24*$settings.new_book_days
54
+ next unless book.title
55
+ next unless pregex.match( book.title )
56
+
57
+ if titles[ book.title ]
58
+ titles[ book.title ] << book.bookcode
59
+ else
60
+ titles[ book.title ] = [ book.bookcode ]
61
+ end
62
+ }
63
+
64
+ # sort by time last imported
65
+ titles = titles.sort { |a, b|
66
+ newest_a = 0
67
+ a[1].each { |bookcode|
68
+ rtime = $db.get_book(bookcode).itime
69
+ newest_a = rtime if rtime and rtime > newest_a
70
+ }
71
+
72
+ newest_b = 0
73
+ b[1].each { |bookcode|
74
+ rtime = $db.get_book(bookcode).itime
75
+ newest_b = rtime if rtime and rtime > newest_b
76
+ }
77
+
78
+ newest_b <=> newest_a
79
+ }
80
+
81
+ html = ''
82
+ titles.each { |title, bookcodes|
83
+ html << "<li class=\"li-title\" bookcodes=\"#{bookcodes.join(',')}\">#{title.escape_html}</li>\n"
84
+ }
85
+ html
86
+ end
87
+
88
+
89
+ # lists books that are unfinish reading
90
+ post '/rlists' do
91
+ content_type :text
92
+
93
+ titles = {}
94
+ $db.books.each { |bookcode, book|
95
+ next unless book.fullpath_valid
96
+ next unless book.page
97
+ next unless book.page < book.pages
98
+ next unless book.title
99
+ next unless pregex.match( book.title )
100
+
101
+ if titles[ book.title ]
102
+ titles[ book.title ] << book.bookcode
103
+ else
104
+ titles[ book.title ] = [ book.bookcode ]
105
+ end
106
+ }
107
+
108
+ # sort by time last read
109
+ titles = titles.sort { |a, b|
110
+ newest_a = 0
111
+ a[1].each { |bookcode|
112
+ rtime = $db.get_book(bookcode).rtime
113
+ newest_a = rtime if rtime and rtime > newest_a
114
+ }
115
+
116
+ newest_b = 0
117
+ b[1].each { |bookcode|
118
+ rtime = $db.get_book(bookcode).rtime
119
+ newest_b = rtime if rtime and rtime > newest_b
120
+ }
121
+
122
+ newest_b <=> newest_a
123
+ }
124
+
125
+ html = ''
126
+ titles.each { |title, bookcodes|
127
+ html << "<li class=\"li-title\" bookcodes=\"#{bookcodes.join(',')}\">#{title.escape_html}</li>\n"
128
+ }
129
+ html
130
+ end
131
+
132
+ # lists books that are finish reading
133
+ post '/flists' do
134
+ content_type :text
135
+
136
+ titles = {}
137
+ $db.books.each { |bookcode, book|
138
+ next unless book.fullpath_valid
139
+ next unless book.page
140
+ next unless book.page == book.pages
141
+ next unless book.title
142
+ next unless pregex.match( book.title )
143
+
144
+ if titles[ book.title ]
145
+ titles[ book.title ] << book.bookcode
146
+ else
147
+ titles[ book.title ] = [ book.bookcode ]
148
+ end
149
+ }
150
+
151
+ # sort by time last read
152
+ titles = titles.sort { |a, b|
153
+ newest_a = 0
154
+ a[1].each { |bookcode|
155
+ rtime = $db.get_book(bookcode).rtime
156
+ newest_a = rtime if rtime and rtime > newest_a
157
+ }
158
+
159
+ newest_b = 0
160
+ b[1].each { |bookcode|
161
+ rtime = $db.get_book(bookcode).rtime
162
+ newest_b = rtime if rtime and rtime > newest_b
163
+ }
164
+
165
+ newest_b <=> newest_a
166
+ }
167
+
168
+ html = ''
169
+ titles.each { |title, bookcodes|
170
+ html << "<li class=\"li-title\" bookcodes=\"#{bookcodes.join(',')}\">#{title.escape_html}</li>\n"
171
+ }
172
+ html
173
+ end
174
+
175
+ # show all unique titles
176
+ post '/alists' do
177
+ content_type :text
178
+
179
+ authors = {}
180
+ $db.books.each { |bookcode, book|
181
+ next unless book.fullpath_valid
182
+ next unless book.author
183
+ next unless pregex.match( book.author )
184
+
185
+ if authors[ book.author ]
186
+ authors[ book.author ] << book.bookcode
187
+ else
188
+ authors[ book.author ] = [ book.bookcode ]
189
+ end
190
+ }
191
+
192
+ # sort by author alphabetically
193
+ authors = authors.sort { |a, b| a[0] <=> b[0] }
194
+
195
+ c = ' ' # double space instead of 0 byte, so book without title or obscure filename can be group and have divider
196
+ html = ''
197
+ authors.each { |author, bookcodes|
198
+ if c != author[0..0]
199
+ # add divider
200
+ c = author[0..0] == '' ? '-' : author[0..0]
201
+
202
+ html << "<li class=\"ui-li-divider\">#{c}</li>"
203
+ end
204
+
205
+ html << "<li class=\"li-title\" bookcodes=\"#{bookcodes.join(',')}\" options=\"sortbyauthor\">#{author.escape_html}</li>\n"
206
+ }
207
+ html
208
+ end
209
+
210
+ # new, combined browse and reader
211
+ get '/tablet' do
212
+ cache_control :public, :must_revalidate, :max_age => 1
213
+
214
+ haml :tablet3, :layout => false
215
+ end
216
+
217
+ # list books ver2
218
+ get '/listbooks' do
219
+ content_type :json
220
+
221
+ bookcodes = request['bookcodes'] ? request['bookcodes'].split(',') : []
222
+ options = request['options'] ? request['options'].split(',') : []
223
+
224
+ books = {}
225
+
226
+ for bookcode in bookcodes
227
+ if $db.has_bookcode?( bookcode )
228
+ book = $db.get_book( bookcode )
229
+
230
+ # book volume/chapter/etc info
231
+ bn = File.basename( book.fullpath )
232
+ bn = bn.gsub( File.extname(bn), '' )
233
+ bn = bn.gsub( book.title, '' )
234
+ # bn = bn.gsub( bn.replace(/\'/,'&#39;'), '' )
235
+ bn = bn.gsub( /(\(.+?\))/, '' )
236
+ bn = bn.gsub( /(\[.+?\])/, '' )
237
+ bn = bn.gsub( /(\[\])/, '' )
238
+ bn = bn.gsub( / +/, ' ' )
239
+ bn.strip!
240
+
241
+ books[bookcode] = {
242
+ :title => book.title,
243
+ :sname => bn,
244
+ :author => book.author,
245
+ :size => book.size,
246
+ :mtime => book.mtime,
247
+ :itime => book.itime,
248
+ :rtime => book.rtime,
249
+ :page => book.page,
250
+ :pages => book.pages
251
+ }
252
+ end
253
+ end
254
+
255
+ JSON.pretty_generate( books )
256
+ end
257
+
258
+ end
259
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ # License: refer to LICENSE file
4
+
5
+ require 'thread'
6
+
7
+ # worker thread for saving database and bookmarks
8
+ def start_auto_save
9
+ # run save every 60 seconds
10
+ Thread.new {
11
+ while true
12
+ $db.save
13
+ $db.save_bookmarks
14
+ sleep 60
15
+ end
16
+ }
17
+ end
18
+
19
+
20
+ # worker thread for generating thumbnails
21
+ def start_auto_gen_thumbnail
22
+ $open_cbz_ltime = Time.now - 61 # holds the last time the open_cbz is called
23
+
24
+ Thread.new {
25
+ puts "************* Start Generating Thumbnails *************"
26
+
27
+ for bookcode, obj in $db.books
28
+ # if the call to open_cbz has elasped more than 60 seconds, allow to resume generating
29
+ if $open_cbz_ltime + 60 < Time.now
30
+ mk_thumb( obj.fullpath, true )
31
+ else
32
+ puts "Thumbnail generating paused."
33
+ sleep 60
34
+ end
35
+ end
36
+
37
+ puts "************* Finish Generating Thumbnails *************"
38
+ }
39
+ end
@@ -0,0 +1,390 @@
1
+ body {
2
+ /*background-color: #eee !important;*/
3
+ }
4
+
5
+ .hidden {
6
+ visibility: hidden;
7
+ }
8
+
9
+ #navtop {
10
+ /*position: fixed;*/
11
+ z-index: 999;
12
+ }
13
+
14
+ #navcollapse {
15
+ z-index: 100;
16
+ background-color: #fafafa;
17
+ }
18
+
19
+ #container2 {
20
+ z-index: 1;
21
+ top: 51px;
22
+ left: 0px;
23
+ position: absolute;
24
+ width: 100%;
25
+ padding: 0px;
26
+ margin: 0px;
27
+ }
28
+ #ul-lists {
29
+ left: 0px;
30
+ position: absolute;
31
+ width: 100%;
32
+ margin: 0px;
33
+ padding: 0px;
34
+ }
35
+
36
+ .lazy img {
37
+ display: block;
38
+ }
39
+
40
+ li {
41
+ position: relative;
42
+ }
43
+
44
+
45
+ /* Portrait tablet to landscape and desktop */
46
+ @media (min-width: 768px) {
47
+ /*@media all and (min-width: 801px) {*/
48
+ .directory, .file {
49
+ width: 160px;
50
+ height: 220px;
51
+ }
52
+ .directory a, .file a {
53
+ min-width: 100%;
54
+ min-height: 220px;
55
+ }
56
+ .directory span, .file a span:first-of-type {
57
+ position: absolute;
58
+ margin-left: auto;
59
+ margin-right: auto;
60
+ bottom: 5px;
61
+ font-size: smaller;
62
+ height: 52px;
63
+ width: 95%;
64
+ padding: 5px;
65
+ overflow: hidden;
66
+ display: block;
67
+ color: #000;
68
+ }
69
+ .directory img, .file img {
70
+ min-height: 100px;
71
+ min-width: 50px;
72
+ max-width: 140px;
73
+ max-height: 140px;
74
+
75
+ position: relative;
76
+ top: 5px;
77
+ margin-left: auto;
78
+ margin-right: auto;
79
+ display: block;
80
+ border-style: solid;
81
+ border-width: 1px;
82
+ border-color: #000;
83
+ box-shadow: 0px 0px 5px #999;
84
+
85
+ transition: max-width 0.2s ease, max-height 0.2s ease;
86
+ }
87
+ .bookpages {
88
+ position: absolute;
89
+ top: 0px;
90
+ right: 0px;
91
+ }
92
+ .file .countdown p {
93
+ position: absolute;
94
+ right: 0px;
95
+ bottom: 0px;
96
+ font-size: 14em;
97
+ line-height: 1em;
98
+ text-align: center;
99
+ color: black;
100
+ }
101
+ }
102
+
103
+ /* Landscape phone to portrait tablet */
104
+ @media (max-width: 767px) {
105
+ #navtop2 {
106
+ padding-left: 20px;
107
+ padding-right: 20px;
108
+ }
109
+ #searchbox2 {
110
+ width: 93%;
111
+ }
112
+ .directory, .file {
113
+ min-width: 24.9%;
114
+ height: 220px;
115
+ }
116
+ .directory a, .file a {
117
+ min-width: 100%;
118
+ height: 220px;
119
+ }
120
+ .directory span, .file a span:first-of-type {
121
+ position: absolute;
122
+ margin-left: auto;
123
+ margin-right: auto;
124
+ bottom: 5px;
125
+ font-size: smaller;
126
+ height: 52px;
127
+ width: 95%;
128
+ padding: 5px;
129
+ overflow: hidden;
130
+ display: block;
131
+ color: #000;
132
+ }
133
+ .directory img, .file img {
134
+ min-height: 100px;
135
+ min-width: 50px;
136
+ max-width: 140px;
137
+ max-height: 140px;
138
+
139
+ position: relative;
140
+ top: 5px;
141
+ /* too small, just let image move itself */
142
+ /*margin-left: auto;*/
143
+ /*margin-right: auto;*/
144
+ display: block;
145
+ border-style: solid;
146
+ border-width: 1px;
147
+ border-color: #000;
148
+ box-shadow: 0px 0px 5px #999;
149
+
150
+ transition: max-width 0.2s ease, max-height 0.2s ease;
151
+ }
152
+ .bookpages {
153
+ position: absolute;
154
+ top: 0px;
155
+ right: 0px;
156
+ }
157
+ .file .countdown p {
158
+ position: absolute;
159
+ right: 0px;
160
+ bottom: 0px;
161
+ font-size: 14em;
162
+ line-height: 1em;
163
+ text-align: center;
164
+ color: black;
165
+ }
166
+ }
167
+
168
+ /* Landscape phones and down */
169
+ @media (max-width: 480px) {
170
+ #navtop2 {
171
+ padding-left: 20px;
172
+ padding-right: 20px;
173
+ }
174
+ #searchbox2 {
175
+ width: 93%;
176
+ }
177
+ .directory, .file {
178
+ min-width: 100%;
179
+ height: 60px;
180
+ }
181
+ .directory a, .file a {
182
+ min-width: 100%;
183
+ height: 60px;
184
+ }
185
+ .directory span, .file a span:first-of-type {
186
+ position: absolute;
187
+ top: 0px;
188
+ font-size: smaller;
189
+ width: 85%;
190
+ height: 55px;
191
+ left: 50px;
192
+ overflow: hidden;
193
+ display: block;
194
+ color: #000;
195
+ /* covers up the .last-selected-item bg-color, so disabled */
196
+ /*background-color: #eee;*/
197
+ }
198
+ .directory img, .file img {
199
+ min-height: 10px;
200
+ min-width: 10px;
201
+ max-width: 50px;
202
+ max-height: 50px;
203
+
204
+ position: relative;
205
+ border-style: solid;
206
+ border-width: 1px;
207
+ border-color: #000;
208
+
209
+ transition: max-width 0.2s ease, max-height 0.2s ease;
210
+ }
211
+ .bookpages {
212
+ position: absolute;
213
+ top: 0px;
214
+ right: 0px;
215
+ }
216
+ .file .countdown p {
217
+ position: absolute;
218
+ right: 50px;
219
+ bottom: 0px;
220
+ font-size: 3em;
221
+ line-height: 1em;
222
+ text-align: center;
223
+ color: black;
224
+ }
225
+ }
226
+
227
+ .last-selected-item {
228
+ /* make the last selected browse item dark lighted */
229
+ background-color: #cdcdcd !important;
230
+ }
231
+
232
+
233
+ .directory, .file {
234
+ float: left;
235
+ /*width: 160px;*/
236
+ /*height: 220px;*/
237
+ /*margin: 10px;*/
238
+ margin: 0px;
239
+ padding: 0px;
240
+ list-style: none;
241
+ /*background-color: #ccc;*/
242
+ }
243
+
244
+ .directory a, .file a {
245
+ /*width: 160px;*/
246
+ /*height: 220px;*/
247
+ display: inline-block;
248
+ position: relative;
249
+ background-color: #eee;
250
+ }
251
+
252
+
253
+ .directory img {
254
+ border: none !important;
255
+ box-shadow: none !important;
256
+ }
257
+
258
+ .file .countdown {
259
+ position: absolute;
260
+ bottom: 0px;
261
+ right: 0px;
262
+ width: 80%;
263
+ height: 80%;
264
+ opacity: 0.3;
265
+ z-index: 10;
266
+ }
267
+ .file .countdown:hover {
268
+ text-decoration: none;
269
+ };
270
+
271
+ /*
272
+ * Read Progress Indicator
273
+ * generated from http://www.colorzilla.com/gradient-editor/
274
+ */
275
+ .read0 {
276
+ /*background-color: #ffece6;*/
277
+ }
278
+ .read5 {
279
+ background: rgb(51,204,102); /* Old browsers */
280
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 5%, rgba(234,234,234,1) 6%); /* FF3.6+ */
281
+ background: -webkit-gradient(linear, left top, right top, color-stop(5%,rgba(51,204,102,1)), color-stop(6%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
282
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 5%,rgba(234,234,234,1) 6%); /* Chrome10+,Safari5.1+ */
283
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 5%,rgba(234,234,234,1) 6%); /* Opera 11.10+ */
284
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 5%,rgba(234,234,234,1) 6%); /* IE10+ */
285
+ background: linear-gradient(to right, rgba(51,204,102,1) 5%,rgba(234,234,234,1) 6%); /* W3C */
286
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
287
+ }
288
+ .read10 {
289
+ background: rgb(51,204,102); /* Old browsers */
290
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 10%, rgba(234,234,234,1) 11%); /* FF3.6+ */
291
+ background: -webkit-gradient(linear, left top, right top, color-stop(10%,rgba(51,204,102,1)), color-stop(11%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
292
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 10%,rgba(234,234,234,1) 11%); /* Chrome10+,Safari5.1+ */
293
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 10%,rgba(234,234,234,1) 11%); /* Opera 11.10+ */
294
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 10%,rgba(234,234,234,1) 11%); /* IE10+ */
295
+ background: linear-gradient(to right, rgba(51,204,102,1) 10%,rgba(234,234,234,1) 11%); /* W3C */
296
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
297
+ }
298
+ .read20 {
299
+ background: rgb(51,204,102); /* Old browsers */
300
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 20%, rgba(234,234,234,1) 21%); /* FF3.6+ */
301
+ background: -webkit-gradient(linear, left top, right top, color-stop(20%,rgba(51,204,102,1)), color-stop(21%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
302
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 20%,rgba(234,234,234,1) 21%); /* Chrome10+,Safari5.1+ */
303
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 20%,rgba(234,234,234,1) 21%); /* Opera 11.10+ */
304
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 20%,rgba(234,234,234,1) 21%); /* IE10+ */
305
+ background: linear-gradient(to right, rgba(51,204,102,1) 20%,rgba(234,234,234,1) 21%); /* W3C */
306
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
307
+ }
308
+ .read30 {
309
+ background: rgb(51,204,102); /* Old browsers */
310
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 30%, rgba(234,234,234,1) 31%); /* FF3.6+ */
311
+ background: -webkit-gradient(linear, left top, right top, color-stop(30%,rgba(51,204,102,1)), color-stop(31%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
312
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 30%,rgba(234,234,234,1) 31%); /* Chrome10+,Safari5.1+ */
313
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 30%,rgba(234,234,234,1) 31%); /* Opera 11.10+ */
314
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 30%,rgba(234,234,234,1) 31%); /* IE10+ */
315
+ background: linear-gradient(to right, rgba(51,204,102,1) 30%,rgba(234,234,234,1) 31%); /* W3C */
316
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
317
+ }
318
+ .read40 {
319
+ background: rgb(51,204,102); /* Old browsers */
320
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 40%, rgba(234,234,234,1) 41%); /* FF3.6+ */
321
+ background: -webkit-gradient(linear, left top, right top, color-stop(40%,rgba(51,204,102,1)), color-stop(41%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
322
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 40%,rgba(234,234,234,1) 41%); /* Chrome10+,Safari5.1+ */
323
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 40%,rgba(234,234,234,1) 41%); /* Opera 11.10+ */
324
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 40%,rgba(234,234,234,1) 41%); /* IE10+ */
325
+ background: linear-gradient(to right, rgba(51,204,102,1) 40%,rgba(234,234,234,1) 41%); /* W3C */
326
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
327
+ }
328
+ .read50 {
329
+ background: rgb(51,204,102); /* Old browsers */
330
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 50%, rgba(234,234,234,1) 51%); /* FF3.6+ */
331
+ background: -webkit-gradient(linear, left top, right top, color-stop(50%,rgba(51,204,102,1)), color-stop(51%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
332
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 50%,rgba(234,234,234,1) 51%); /* Chrome10+,Safari5.1+ */
333
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 50%,rgba(234,234,234,1) 51%); /* Opera 11.10+ */
334
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 50%,rgba(234,234,234,1) 51%); /* IE10+ */
335
+ background: linear-gradient(to right, rgba(51,204,102,1) 50%,rgba(234,234,234,1) 51%); /* W3C */
336
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
337
+ }
338
+ .read60 {
339
+ background: rgb(51,204,102); /* Old browsers */
340
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 60%, rgba(234,234,234,1) 61%); /* FF3.6+ */
341
+ background: -webkit-gradient(linear, left top, right top, color-stop(60%,rgba(51,204,102,1)), color-stop(61%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
342
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 60%,rgba(234,234,234,1) 61%); /* Chrome10+,Safari5.1+ */
343
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 60%,rgba(234,234,234,1) 61%); /* Opera 11.10+ */
344
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 60%,rgba(234,234,234,1) 61%); /* IE10+ */
345
+ background: linear-gradient(to right, rgba(51,204,102,1) 60%,rgba(234,234,234,1) 61%); /* W3C */
346
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
347
+ }
348
+ .read70 {
349
+ background: rgb(51,204,102); /* Old browsers */
350
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 70%, rgba(234,234,234,1) 71%); /* FF3.6+ */
351
+ background: -webkit-gradient(linear, left top, right top, color-stop(70%,rgba(51,204,102,1)), color-stop(71%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
352
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 70%,rgba(234,234,234,1) 71%); /* Chrome10+,Safari5.1+ */
353
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 70%,rgba(234,234,234,1) 71%); /* Opera 11.10+ */
354
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 70%,rgba(234,234,234,1) 71%); /* IE10+ */
355
+ background: linear-gradient(to right, rgba(51,204,102,1) 70%,rgba(234,234,234,1) 71%); /* W3C */
356
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
357
+ }
358
+ .read80 {
359
+ background: rgb(51,204,102); /* Old browsers */
360
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 80%, rgba(234,234,234,1) 81%); /* FF3.6+ */
361
+ background: -webkit-gradient(linear, left top, right top, color-stop(80%,rgba(51,204,102,1)), color-stop(81%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
362
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 80%,rgba(234,234,234,1) 81%); /* Chrome10+,Safari5.1+ */
363
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 80%,rgba(234,234,234,1) 81%); /* Opera 11.10+ */
364
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 80%,rgba(234,234,234,1) 81%); /* IE10+ */
365
+ background: linear-gradient(to right, rgba(51,204,102,1) 80%,rgba(234,234,234,1) 81%); /* W3C */
366
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
367
+ }
368
+ .read90 {
369
+ background: rgb(51,204,102); /* Old browsers */
370
+ background: -moz-linear-gradient(left, rgba(51,204,102,1) 90%, rgba(234,234,234,1) 91%); /* FF3.6+ */
371
+ background: -webkit-gradient(linear, left top, right top, color-stop(90%,rgba(51,204,102,1)), color-stop(91%,rgba(234,234,234,1))); /* Chrome,Safari4+ */
372
+ background: -webkit-linear-gradient(left, rgba(51,204,102,1) 90%,rgba(234,234,234,1) 91%); /* Chrome10+,Safari5.1+ */
373
+ background: -o-linear-gradient(left, rgba(51,204,102,1) 90%,rgba(234,234,234,1) 91%); /* Opera 11.10+ */
374
+ background: -ms-linear-gradient(left, rgba(51,204,102,1) 90%,rgba(234,234,234,1) 91%); /* IE10+ */
375
+ background: linear-gradient(to right, rgba(51,204,102,1) 90%,rgba(234,234,234,1) 91%); /* W3C */
376
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33cc66', endColorstr='#eaeaea',GradientType=1 ); /* IE6-9 */
377
+ }
378
+ .read100 {
379
+ background-color: #33cc66 !important;
380
+ }
381
+
382
+ .breadcrumb2 {
383
+ line-height: 40px;
384
+ padding: 0;
385
+ margin: 0;
386
+ float: left;
387
+ /* make background almost transparent, use #fafafa as base and 0.5 for opacity */
388
+ background-color:rgba(250, 250, 250, 0.5);
389
+ /*background-color: #fafafa;*/
390
+ }