mirror of
https://github.com/ajurna/cbwebreader.git
synced 2026-11-02 18:46:53 +00:00
**Refactor directory scanning and add scan task support**
- Added a new `scan_directory` task to enable folder scans as asynchronous tasks while maintaining compatibility with the immediate backend. - Introduced the `reconcile` function, replacing `generate_directory` for improved separation of concerns between database writes and read operations. - Established a unique constraint on `Directory` (`one_directory_name_per_parent`) to prevent duplicate directories under the same parent. - Added a "Scan" button to the frontend for re-reading folders from disk, along with new task invocation endpoints in the API. - Updated tests across modules to validate the new `scan_directory` task, unique constraints, and database indexing logic. - Improved cleanup logic for stale files, directories, and thumbnails to handle concurrent operations efficiently. - Simplified `scan_comics` management command by removing user dependency and aligning it with the new `reconcile` function. - Enhanced frontend components (`TheComicReader`, `TheComicList`, and others) to include lifecycle method cleanups, prevent memory leaks, and handle task-based scans.
This commit is contained in:
1 parent
4d0ba750ad
commit
ce809ed1a9
18 files changed
+364
-81
No files matched your search
@@ -136,6 +136,9 @@ export default {
|
||||
mounted() {
|
||||
this.updateComicList()
|
||||
},
|
||||
beforeUnmount() {
|
||||
clearTimeout(this.timeout)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
<li><a class="dropdown-item" @click="markAll('mark_unread')"><font-awesome-icon icon='book' />Mark Un-read</a></li>
|
||||
<li><a class="dropdown-item" @click="markAll('mark_read')"><font-awesome-icon icon='book-open' />Mark read</a></li>
|
||||
</ul>
|
||||
<button type="button" class="btn btn-outline-secondary" :disabled="scanning" title="Read this folder from disk again" @click="scanFolder">
|
||||
<font-awesome-icon icon='refresh' />{{ scanning ? 'Scanning…' : 'Scan' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row row-cols-2 row-cols-sm-3 row-cols-md-4 row-cols-lg-6 row-cols-xl-auto mt-1" >
|
||||
@@ -49,7 +52,8 @@ export default {
|
||||
filter_read: false,
|
||||
filter_unread: false
|
||||
},
|
||||
loading: true
|
||||
loading: true,
|
||||
scanning: false
|
||||
}},
|
||||
props: {
|
||||
selector: String
|
||||
@@ -68,6 +72,18 @@ export default {
|
||||
})
|
||||
.catch((error) => {console.log(error)})
|
||||
},
|
||||
scanFolder () {
|
||||
this.scanning = true
|
||||
api.post('/api/browse/scan/', { selector: this.selector || null })
|
||||
.then(response => {
|
||||
this.comics = response.data
|
||||
this.scanning = false
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
this.scanning = false
|
||||
})
|
||||
},
|
||||
markPreviousRead (selector) {
|
||||
let selectors = []
|
||||
this.comics.every((item) => {
|
||||
|
||||
@@ -131,10 +131,11 @@ export default {
|
||||
}).then(() => {
|
||||
this.deck.slide(this.current_page)
|
||||
api.put(set_read_url, {page: this.current_page})
|
||||
this.deck.on( 'slidechanged', (event) => {
|
||||
this.slideChanged = (event) => {
|
||||
this.$refs.comic_box.scrollIntoView({behavior: 'smooth'})
|
||||
api.put(set_read_url, {page: event.indexh})
|
||||
});
|
||||
}
|
||||
this.deck.on('slidechanged', this.slideChanged);
|
||||
})
|
||||
|
||||
this.hammertime = new Hammer(this.$refs.comic_box, {})
|
||||
@@ -153,6 +154,17 @@ export default {
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('keyup', this.keyPressDebounce)
|
||||
clearTimeout(this.key_timeout)
|
||||
if (this.deck) {
|
||||
if (this.slideChanged) {
|
||||
this.deck.off('slidechanged', this.slideChanged)
|
||||
}
|
||||
try {
|
||||
this.deck.destroy()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.hammertime.off('swipeleft')
|
||||
this.hammertime.off('swiperight')
|
||||
|
||||
@@ -175,6 +175,9 @@ export default {
|
||||
this.feed_id = response.data.feed_id
|
||||
})
|
||||
},
|
||||
beforeUnmount() {
|
||||
clearTimeout(this.timeout)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
|
||||
/* import specific icons */
|
||||
import {faBook, faBookOpen, faEdit, faTurnUp, faTimes, faCheck} from '@fortawesome/free-solid-svg-icons'
|
||||
library.add(faBook, faBookOpen, faEdit, faTurnUp, faTimes, faCheck)
|
||||
import {faBook, faBookOpen, faEdit, faTurnUp, faTimes, faCheck, faRefresh} from '@fortawesome/free-solid-svg-icons'
|
||||
library.add(faBook, faBookOpen, faEdit, faTurnUp, faTimes, faCheck, faRefresh)
|
||||
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
|
||||
@@ -15,25 +15,20 @@ export default {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
comic_data: {},
|
||||
comic_loaded: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateType() {
|
||||
let comic_data_url = '/api/read/' + this.selector + '/type/'
|
||||
api.get(comic_data_url)
|
||||
.then(response => {
|
||||
checkComicExists() {
|
||||
api.get('/api/read/' + this.selector + '/type/')
|
||||
.then(() => {
|
||||
this.comic_loaded = true
|
||||
})
|
||||
.catch((error) => {console.log(error)})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.updateType()
|
||||
},
|
||||
beforeUpdate() {
|
||||
this.updateType()
|
||||
this.checkComicExists()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in new issue
Block a user