Skip to content
Permalink
Browse files

Close #67

  • Loading branch information...
askosh committed Sep 27, 2019
1 parent d9c4bbe commit 2ebebe2facd308bbabdfffe0105d7d5bd29c3f69
@@ -0,0 +1 @@
var PullToRefresh = {};
@@ -9,12 +9,25 @@
</head>
<body>

<div id="app">
<div class="pull-to-load-indicator hide"></div>

<div id="ptr">
<span class="genericon genericon-next"><i class="icon ion-ios-arrow-round-down-"></i></span>
<div class="loading">
<div class="icon"></div>
<span id="l1"></span>
<span id="l2"></span>
<span id="l3"></span>
</div>
</div>
</div>

<div id="app">
<div class="loading">
<div class="icon"></div>
</div>
</div>

<script src="resources/js/hammer.2.0.4.js"></script>
<script src="resources/js/wptr.1.1.js"></script>
<script src="app.min.js"></script>
<script>ivory.core.run();</script>

@@ -103,6 +103,30 @@ a.button {
margin-top: 20px;
}

/**
--------------------------------------------------------------------------------
PULL TO REFRESH
--------------------------------------------------------------------------------
*/
.pull-to-load-indicator {
width: 30px;
height: 30px;
line-height: 30px;
font-size: 23px;
color: #777;
text-align: center;
background: #eee;
border-radius: 100%;
z-index: 99999;
position: absolute;
top: 48px;
left: calc(50% - 15px);
}

.pull-to-load-indicator.hide {
display: none;
}

/**
--------------------------------------------------------------------------------
HEADER BAR
@@ -113,7 +137,7 @@ HEADER BAR
background: linear-gradient(#fff, #fbfbfb);
box-shadow: 0 1px 10px rgba(0,0,0,.05);
border-bottom: 0.75px solid #e5e5e5;
z-index: 10;
z-index: 5;
position: fixed;
top: 0;
left: 0;
@@ -533,7 +557,7 @@ POP
LOADING
--------------------------------------------------------------------------------
*/
.loading {
#app .loading {
display: flex;
width: 100%;
height: 100%;
@@ -547,7 +571,7 @@ LOADING
left: 0;
}

.loading .icon {
#app .loading .icon {
width: 40px;
height: 40px;
background: url(../images/icon.png) no-repeat;
@@ -568,6 +592,6 @@ LOADING
}
}

.loading .text {
#app .loading .text {
margin-top: 50px;
}

Large diffs are not rendered by default.

@@ -0,0 +1,235 @@
var WebPullToRefresh = (function () {
'use strict';

/**
* Hold all of the default parameters for the module
* @type {object}
*/
var defaults = {
// ID of the element holding pannable content area
contentEl: 'content',

// ID of the element holding pull to refresh loading area
ptrEl: 'ptr',

// Number of pixels of panning until refresh
distanceToRefresh: 25,

// Pointer to function that does the loading and returns a promise
loadingFunction: false,

// Dragging resistance level
resistance: 6
};

/**
* Hold all of the merged parameter and default module options
* @type {object}
*/
var options = {};

/**
* Pan event parameters
* @type {object}
*/
var pan = {
enabled: false,
distance: 0,
startingPositionY: 0
};

/**
* Easy shortener for handling adding and removing body classes.
*/
var bodyClass = document.body.classList;

/**
* Initialize pull to refresh, hammer, and bind pan events.
*
* @param {object=} params - Setup parameters for pull to refresh
*/
var init = function( params ) {
params = params || {};
options = {
contentEl: params.contentEl || document.getElementById( defaults.contentEl ),
ptrEl: params.ptrEl || document.getElementById( defaults.ptrEl ),
distanceToRefresh: params.distanceToRefresh || defaults.distanceToRefresh,
loadingFunction: params.loadingFunction || defaults.loadingFunction,
resistance: params.resistance || defaults.resistance
};

if ( ! options.contentEl || ! options.ptrEl ) {
return false;
}

var h = new Hammer( options.contentEl );

h.get( 'pan' ).set( { direction: Hammer.DIRECTION_VERTICAL } );

h.on( 'panstart', _panStart );
h.on( 'pandown', _panDown );
h.on( 'panup', _panUp );
h.on( 'panend', _panEnd );
};

/**
* Determine whether pan events should apply based on scroll position on panstart
*
* @param {object} e - Event object
*/
var _panStart = function(e) {
pan.startingPositionY = document.body.scrollTop;

if ( pan.startingPositionY === 0 ) {
pan.enabled = true;
}
};

/**
* Handle element on screen movement when the pandown events is firing.
*
* @param {object} e - Event object
*/
var _panDown = function(e) {
if ( ! pan.enabled ) {
return;
}

e.preventDefault();
pan.distance = e.distance / options.resistance;

_setContentPan();
_setBodyClass();
};

/**
* Handle element on screen movement when the pandown events is firing.
*
* @param {object} e - Event object
*/
var _panUp = function(e) {
if ( ! pan.enabled || pan.distance === 0 ) {
return;
}

e.preventDefault();

if ( pan.distance < e.distance / options.resistance ) {
pan.distance = 0;
} else {
pan.distance = e.distance / options.resistance;
}

_setContentPan();
_setBodyClass();
};

/**
* Set the CSS transform on the content element to move it on the screen.
*/
var _setContentPan = function() {

// If the pan.distance is higher than 0, show it, and add it an icon
if(pan.distance > 0) {

document.querySelector('.pull-to-load-indicator').classList.remove('hide');
document.querySelector('.pull-to-load-indicator').innerHTML = '<i class="icon ion-ios-arrow-round-down"></i>';

}

// Move the indicator as you pull down
document.querySelector('.pull-to-load-indicator').style.marginTop = pan.distance + 'px';

// When we reach the distance to refresh, change icon and hide the icon
if(pan.distance > options.distanceToRefresh) {

document.querySelector('.pull-to-load-indicator').innerHTML = '<i class="icon ion-ios-checkmark"></i>';


}

webkit.messageHandlers.ivorySetMessage.postMessage(pan.distance)
// Use transforms to smoothly animate elements on desktop and mobile devices
//options.contentEl.style.transform = options.contentEl.style.webkitTransform = 'translate3d( 0, ' + pan.distance + 'px, 0 )';
//options.ptrEl.style.transform = options.ptrEl.style.webkitTransform = 'translate3d( 0, ' + ( pan.distance - options.ptrEl.offsetHeight ) + 'px, 0 )';
};

/**
* Set/remove the loading body class to show or hide the loading indicator after pull down.
*/
var _setBodyClass = function() {
if ( pan.distance > options.distanceToRefresh ) {
bodyClass.add( 'ptr-refresh' );
} else {
bodyClass.remove( 'ptr-refresh' );
}
};

/**
* Determine how to animate and position elements when the panend event fires.
*
* @param {object} e - Event object
*/
var _panEnd = function(e) {
if ( ! pan.enabled ) {
return;
}

e.preventDefault();

options.contentEl.style.transform = options.contentEl.style.webkitTransform = '';
options.ptrEl.style.transform = options.ptrEl.style.webkitTransform = '';

if ( document.body.classList.contains( 'ptr-refresh' ) ) {
_doLoading();
} else {
_doReset();
}

pan.distance = 0;
pan.enabled = false;
};

/**
* Position content and refresh elements to show that loading is taking place.
*/
var _doLoading = function() {
bodyClass.add( 'ptr-loading' );

// If no valid loading function exists, just reset elements
if ( ! options.loadingFunction ) {
return _doReset();
}

// The loading function should return a promise
var loadingPromise = options.loadingFunction();

// For UX continuity, make sure we show loading for at least one second before resetting
setTimeout( function() {
// Once actual loading is complete, reset pull to refresh
loadingPromise.then( _doReset );
document.querySelector('.pull-to-load-indicator').classList.add('hide');
}, 1000 );
};

/**
* Reset all elements to their starting positions before any paning took place.
*/
var _doReset = function() {
bodyClass.remove( 'ptr-loading' );
bodyClass.remove( 'ptr-refresh' );
bodyClass.add( 'ptr-reset' );

var bodyClassRemove = function() {
bodyClass.remove( 'ptr-reset' );
document.body.removeEventListener( 'transitionend', bodyClassRemove, false );
};

document.body.addEventListener( 'transitionend', bodyClassRemove, false );
};

return {
init: init
}

})();
@@ -27,7 +27,12 @@
(app-view view)))

(defn- set-up []
(utils/listen-for-viewport-change (fn [screen-width] (rf/dispatch [::events/set-screen-width screen-width]))))
(utils/listen-for-viewport-change (fn [screen-width] (rf/dispatch [::events/set-screen-width screen-width])))
(utils/listen-for-pull-event (fn []
(let [timeline @(rf/subscribe [::subscriptions/timeline])]
(cond
(= :notifications timeline) (rf/dispatch [::events/get-newer-notifications])
:else (rf/dispatch [::events/get-newer-toots timeline]))))))

(defn ^:export run []
(rf/dispatch-sync [::events/initialize])
@@ -113,6 +113,27 @@
(rf/dispatch [::set-toots timeline (get response :body)])))
{})))

(rf/reg-event-fx
::get-newer-toots
(fn [cofx [_ timeline]]
(let [url (get-in cofx [:db :instance-url])
token (get-in cofx [:db :access-token])
toots (get-in cofx [:db :toots timeline])
since-id (get (first toots) :id)
timeline-raw (cond
(or (= :local timeline)
(= :federated timeline)) "public"
:else (subs (str timeline) 1))
query-params (cond (= :local timeline) {:local true
:since_id since-id}
:else {:since_id since-id})]
(go (let [response (<! (http/get (str "https://" url "/api/v1/timelines/" timeline-raw)
{:with-credentials? false
:query-params query-params
:headers {"Authorization" (str "Bearer " token)}}))]
(rf/dispatch [::set-toots timeline (concat toots (get response :body))])))
{})))

(rf/reg-event-fx
::get-older-toots
(fn [cofx [_ timeline]]
@@ -23,7 +23,7 @@
{:on-click (get btn :callback)
:class (get btn :class)}
[:i.icon {:class (get btn :icon)}]])])

(defn content [& content]
(into [:div.content] content))

0 comments on commit 2ebebe2

Please sign in to comment.
You can’t perform that action at this time.