1
0
mirror of https://github.com/flarum/core.git synced 2025-08-02 06:30:53 +02:00

Replace Ember app with Mithril app

This commit is contained in:
Toby Zerner
2015-04-25 22:28:39 +09:30
parent 6f67b8c247
commit b68a4711dc
377 changed files with 5641 additions and 7330 deletions

View File

@@ -0,0 +1,43 @@
export default class History {
constructor() {
this.stack = [];
this.push('index', '/');
}
top() {
return this.stack[this.stack.length - 1];
}
push(name, url) {
var url = url || m.route();
// maybe? prevents browser back button from breaking history
var secondTop = this.stack[this.stack.length - 2];
if (secondTop && secondTop.name === name) {
this.stack.pop();
}
var top = this.top();
if (top && top.name === name) {
top.url = url;
} else {
this.stack.push({name: name, url: url});
}
}
canGoBack() {
return this.stack.length > 1;
}
back() {
this.stack.pop();
var top = this.top();
m.route(top.url);
}
home() {
this.stack.splice(1);
var top = this.top();
m.route(top.url);
}
}

View File

@@ -0,0 +1,50 @@
export default class Pane {
constructor(element) {
this.pinnedKey = 'panePinned';
this.$element = $(element);
this.pinned = localStorage.getItem(this.pinnedKey) !== 'false';
this.active = false;
this.showing = false;
this.render();
}
enable() {
this.active = true;
this.render();
}
disable() {
this.active = false;
this.showing = false;
this.render();
}
show() {
clearTimeout(this.hideTimeout);
this.showing = true;
this.render();
}
hide() {
this.showing = false;
this.render();
}
onmouseleave() {
this.hideTimeout = setTimeout(this.hide.bind(this), 250);
}
togglePinned() {
localStorage.setItem(this.pinnedKey, (this.pinned = !this.pinned) ? 'true' : 'false');
this.render();
}
render() {
this.$element
.toggleClass('pane-pinned', this.pinned)
.toggleClass('has-pane', this.active)
.toggleClass('pane-showing', this.showing);
}
}

View File

@@ -0,0 +1,155 @@
export default class PostStream {
constructor(discussion) {
this.discussion = discussion
this.ids = this.discussion.data().links.posts.linkage.map((link) => link.id)
var item = this.makeItem(0, this.ids.length - 1)
item.loading = true
this.content = [item]
this.postLoadCount = 20
}
count() {
return this.ids.length;
}
loadedCount() {
return this.content.filter((item) => item.post).length;
}
loadRange(start, end, backwards) {
// Find the appropriate gap objects in the post stream. When we find
// one, we will turn on its loading flag.
this.content.forEach(function(item) {
if (!item.post && ((item.start >= start && item.start <= end) || (item.end >= start && item.end <= end))) {
item.loading = true
item.direction = backwards ? 'up' : 'down'
}
});
// Get a list of post numbers that we'll want to retrieve. If there are
// more post IDs than the number of posts we want to load, then take a
// slice of the array in the appropriate direction.
var ids = this.ids.slice(start, end + 1);
var limit = this.postLoadCount
ids = backwards ? ids.slice(-limit) : ids.slice(0, limit)
return this.loadPosts(ids)
}
loadPosts(ids) {
if (!ids.length) {
return m.deferred().resolve().promise;
}
return app.store.find('posts', ids).then(this.addPosts.bind(this));
}
loadNearNumber(number) {
// Find the item in the post stream which is nearest to this number. If
// it turns out the be the actual post we're trying to load, then we can
// return a resolved promise (i.e. we don't need to make an API
// request.) Or, if it's a gap, we'll switch on its loading flag.
var item = this.findNearestToNumber(number)
if (item) {
if (item.post && item.post.number() === number) {
return m.deferred().resolve([item.post]).promise;
} else if (!item.post) {
item.direction = 'down'
item.loading = true;
}
}
var stream = this
return app.store.find('posts', {
discussions: this.discussion.id(),
near: number,
count: this.postLoadCount
}).then(this.addPosts.bind(this))
}
loadNearIndex(index, backwards) {
// Find the item in the post stream which is nearest to this index. If
// it turns out the be the actual post we're trying to load, then we can
// return a resolved promise (i.e. we don't need to make an API
// request.) Or, if it's a gap, we'll switch on its loading flag.
var item = this.findNearestToIndex(index)
if (item) {
if (item.post) {
return m.deferred().resolve([item.post]).promise;
}
return this.loadRange(Math.max(item.start, index - this.postLoadCount / 2), item.end, backwards);
}
}
addPosts(posts) {
posts.forEach(this.addPost.bind(this))
}
addPost(post) {
var index = this.ids.indexOf(post.id())
var content = this.content
var makeItem = this.makeItem
// Here we loop through each item in the post stream, and find the gap
// in which this post should be situated. When we find it, we can replace
// it with the post, and new gaps either side if appropriate.
content.some(function(item, i) {
if (item.start <= index && item.end >= index) {
var newItems = []
if (item.start < index) {
newItems.push(makeItem(item.start, index - 1))
}
newItems.push(makeItem(index, index, post))
if (item.end > index) {
newItems.push(makeItem(index + 1, item.end))
}
var args = [i, 1].concat(newItems);
[].splice.apply(content, args)
return true
}
})
}
addPostToEnd(post) {
var index = this.ids.length
this.ids.push(post.id())
this.content.push(this.makeItem(index, index, post))
}
removePost(post) {
this.ids.splice(this.ids.indexOf(post.id()), 1);
this.content.some((item, i) => {
if (item.post === post) {
this.content.splice(i, 1);
return true;
}
});
}
makeItem(start, end, post) {
var item = {start, end}
if (post) {
item.post = post
}
return item
}
findNearestTo(index, property) {
var nearestItem
this.content.some(function(item) {
if (property(item) > index) { return true }
nearestItem = item
})
return nearestItem
}
findNearestToNumber(number) {
return this.findNearestTo(number, (item) => item.post && item.post.number())
}
findNearestToIndex(index) {
return this.findNearestTo(index, (item) => item.start)
}
}