kamishibai 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ }