add classic mobile as a system plugin

This commit is contained in:
Andrew Dolgov 2013-03-26 18:55:57 +04:00
parent 554f658c0e
commit 9d9ed2b32a
37 changed files with 2200 additions and 0 deletions

View file

@ -0,0 +1,32 @@
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
header('Content-Type: text/html; charset=utf-8');
define('MOBILE_VERSION', true);
$basedir = dirname(dirname(dirname(__FILE__)));
set_include_path(
dirname(__FILE__) . PATH_SEPARATOR .
$basedir . PATH_SEPARATOR .
"$basedir/include" . PATH_SEPARATOR .
get_include_path());
require_once "config.php";
require_once "mobile-functions.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
init_connection($link);
login_sequence($link, true);
$id = db_escape_string($link, $_REQUEST["id"]);
$feed_id = db_escape_string($link, $_REQUEST["feed"]);
$cat_id = db_escape_string($link, $_REQUEST["cat"]);
$is_cat = db_escape_string($link, $_REQUEST["is_cat"]);
render_article($link, $id, $feed_id, $cat_id, $is_cat);
?>

View file

@ -0,0 +1,63 @@
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
header('Content-Type: text/html; charset=utf-8');
$basedir = dirname(dirname(dirname(__FILE__)));
set_include_path(
dirname(__FILE__) . PATH_SEPARATOR .
$basedir . PATH_SEPARATOR .
"$basedir/include" . PATH_SEPARATOR .
get_include_path());
define('MOBILE_VERSION', true);
require_once "config.php";
require_once "mobile-functions.php";
require_once "functions.php";
require_once "sessions.php";
require_once "version.php";
require_once "db-prefs.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
init_connection($link);
if (!$_SESSION["uid"]) return;
$op = $_REQUEST["op"];
switch ($op) {
case "toggleMarked":
$cmode = db_escape_string($link, $_REQUEST["mark"]);
$id = db_escape_string($link, $_REQUEST["id"]);
markArticlesById($link, array($id), $cmode);
break;
case "togglePublished":
$cmode = db_escape_string($link, $_REQUEST["pub"]);
$id = db_escape_string($link, $_REQUEST["id"]);
publishArticlesById($link, array($id), $cmode);
break;
case "toggleUnread":
$cmode = db_escape_string($link, $_REQUEST["unread"]);
$id = db_escape_string($link, $_REQUEST["id"]);
catchupArticlesById($link, array($id), $cmode);
break;
case "setPref":
$id = db_escape_string($link, $_REQUEST["id"]);
$value = db_escape_string($link, $_REQUEST["to"]);
mobile_set_pref($link, $id, $value);
print_r($_SESSION);
break;
default:
print json_encode(array("error", "UNKNOWN_METHOD"));
break;
}
?>

29
plugins/mobile/cat.php Normal file
View file

@ -0,0 +1,29 @@
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
header('Content-Type: text/html; charset=utf-8');
define('MOBILE_VERSION', true);
$basedir = dirname(dirname(dirname(__FILE__)));
set_include_path(
dirname(__FILE__) . PATH_SEPARATOR .
$basedir . PATH_SEPARATOR .
"$basedir/include" . PATH_SEPARATOR .
get_include_path());
require_once "config.php";
require_once "mobile-functions.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
init_connection($link);
login_sequence($link, true);
$cat_id = db_escape_string($link, $_REQUEST["id"]);
render_category($link, $cat_id);
?>

33
plugins/mobile/feed.php Normal file
View file

@ -0,0 +1,33 @@
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
header('Content-Type: text/html; charset=utf-8');
define('MOBILE_VERSION', true);
$basedir = dirname(dirname(dirname(__FILE__)));
set_include_path(
dirname(__FILE__) . PATH_SEPARATOR .
$basedir . PATH_SEPARATOR .
"$basedir/include" . PATH_SEPARATOR .
get_include_path());
require_once "config.php";
require_once "mobile-functions.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
init_connection($link);
login_sequence($link, true);
$feed_id = db_escape_string($link, $_REQUEST["id"]);
$cat_id = db_escape_string($link, $_REQUEST["cat"]);
$offset = (int) db_escape_string($link, $_REQUEST["skip"]);
$search = db_escape_string($link, $_REQUEST["search"]);
$is_cat = (bool) db_escape_string($link, $_REQUEST["is_cat"]);
render_headlines_list($link, $feed_id, $cat_id, $offset, $search, $is_cat);
?>

33
plugins/mobile/home.php Normal file
View file

@ -0,0 +1,33 @@
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
header('Content-Type: text/html; charset=utf-8');
define('MOBILE_VERSION', true);
$basedir = dirname(dirname(dirname(__FILE__)));
set_include_path(
dirname(__FILE__) . PATH_SEPARATOR .
$basedir . PATH_SEPARATOR .
"$basedir/include" . PATH_SEPARATOR .
get_include_path());
require_once "config.php";
require_once "mobile-functions.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
init_connection($link);
login_sequence($link, true);
$use_cats = mobile_get_pref($link, 'ENABLE_CATS');
$offset = (int) db_escape_string($link, $_REQUEST["skip"]);
if ($use_cats) {
render_categories_list($link);
} else {
render_flat_feed_list($link, $offset);
}
?>

90
plugins/mobile/index.php Normal file
View file

@ -0,0 +1,90 @@
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
header('Content-Type: text/html; charset=utf-8');
define('MOBILE_VERSION', true);
$basedir = dirname(dirname(dirname(__FILE__)));
set_include_path(
dirname(__FILE__) . PATH_SEPARATOR .
$basedir . PATH_SEPARATOR .
"$basedir/include" . PATH_SEPARATOR .
get_include_path());
require_once "config.php";
require_once "mobile-functions.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
init_connection($link);
login_sequence($link, true);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Tiny Tiny RSS</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<link rel="apple-touch-icon" href="iui/iui-logo-touch-icon.png" />
<meta name="apple-touch-fullscreen" content="YES" />
<style type="text/css" media="screen">@import "iui/iui.css";</style>
<script type="application/x-javascript" src="iui/iui.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" src="../../lib/prototype.js"></script>
<script type="text/javascript" src="mobile.js"></script>
<style type="text/css" media="screen">@import "mobile.css";</style>
</head>
<style type="text/css">
img { max-width : 75%; }
li.oldItem {
color : gray;
}
#myBackButton {
display: none;
left: 6px;
right: auto;
padding: 0;
max-width: 55px;
border-width: 0 8px 0 14px;
-webkit-border-image: url(iui/backButton.png) 0 8 0 14;
}
img.tinyIcon {
max-width : 16px;
max-height : 16px;
margin-right : 10px;
vertical-align : middle;
}
a img {
border-width : 0px;
}
</style>
<body>
<div class="toolbar">
<h1 id="pageTitle"></h1>
<a id="myBackButton" class="button" href="#"></a>
<a class="button" href="prefs.php">Preferences</a>
</div>
<?php
$use_cats = mobile_get_pref($link, 'ENABLE_CATS');
$offset = (int) db_escape_string($link, $_REQUEST["skip"]);
if ($use_cats) {
render_categories_list($link);
} else {
render_flat_feed_list($link, $offset);
}
?>
</body>
</html>

47
plugins/mobile/init.php Normal file
View file

@ -0,0 +1,47 @@
<?php
class Mobile extends Plugin implements IHandler {
private $link;
private $host;
function about() {
return array(1.0,
"Classic mobile version for tt-rss (unsupported)",
"fox",
true);
}
function init($host) {
$this->link = $host->get_link();
$this->host = $host;
$host->add_handler("mobile", "index", $this);
}
function index() {
header("Content-type: text/html; charset=utf-8");
login_sequence($this->link);
header("Location: plugins/mobile/index.php");
}
/* function get_js() {
return file_get_contents(dirname(__FILE__) . "/digest.js");
} */
function csrf_ignore($method) {
return true; //in_array($method, array("index"));
}
function before($method) {
return true;
}
function after() {
}
}
?>

View file

@ -0,0 +1,21 @@
Copyright (c) 2007-2009, iUI Project Members
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the iUI Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,33 @@
NOTICE.txt - iUI credits and copyright notices
iUI is Copyright (c) 2007-2009 by the iUI project members:
M. Sean Gilligan (msgilligan)
Past members:
Joe Hewitt (joehewitt)
Christopher Allen (ChristopherA)
CREDITS
schlueter - committed fixes for issues #9, #11, #63 -- added samples
??? - created iUI icon
kris.tate - named it "iUI", created Google Code project, initial checkin
others - let us know if we missed you
iUI users - thanks for your patience, feedback, and bug reports
THIRD PARTY COMPONENTS
* iUI includes software developed by the Mozilla Project
Copyright (c) 1997-2007, Netscape Communications Corporation and others.
All rights reserved.
http://www.mozilla.org/rhino/
* iUI includes software developed by the Dojo Foundation
http://dojotoolkit.org/docs/shrinksafe
* iUI includes software developed by LCA Soft Ltd.
http://www.lcasoft.com/compress-js.html
* iUI includes software developed by the ant-googlcode Project
http://code.google.com/p/ant-googlecode/

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

398
plugins/mobile/iui/iui.css Normal file
View file

@ -0,0 +1,398 @@
/* iui.css (c) 2007-9 by iUI Project Members, see LICENSE.txt for license */
body {
margin: 0;
font-family: Helvetica;
background: #FFFFFF;
color: #000000;
overflow-x: hidden;
-webkit-user-select: none;
-webkit-text-size-adjust: none;
}
body > *:not(.toolbar) {
display: none;
position: absolute;
margin: 0;
padding: 0;
left: 0;
top: 45px;
width: 100%;
min-height: 372px;
-webkit-transition-duration: 300ms;
-webkit-transition-property: -webkit-transform;
-webkit-transform: translateX(0%);
}
body[orient="landscape"] > *:not(.toolbar) {
min-height: 268px;
}
body > *[selected="true"] {
display: block;
}
a[selected], a:active {
background-color: #194fdb !important;
background-image: url(listArrowSel.png), url(selection.png) !important;
background-repeat: no-repeat, repeat-x;
background-position: right center, left top;
color: #FFFFFF !important;
}
a[selected="progress"] {
background-image: url(loading.gif), url(selection.png) !important;
}
/************************************************************************************************/
body > .toolbar {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
border-bottom: 1px solid #2d3642;
border-top: 1px solid #6d84a2;
padding: 10px;
height: 45px;
background: url(toolbar.png) #6d84a2 repeat-x;
}
.toolbar > h1 {
position: absolute;
overflow: hidden;
left: 50%;
margin: 1px 0 0 -75px;
height: 45px;
font-size: 20px;
width: 150px;
font-weight: bold;
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
color: #FFFFFF;
}
body[orient="landscape"] > .toolbar > h1 {
margin-left: -125px;
width: 250px;
}
.button {
position: absolute;
overflow: hidden;
top: 8px;
right: 6px;
margin: 0;
border-width: 0 5px;
padding: 0 3px;
width: auto;
height: 30px;
line-height: 30px;
font-family: inherit;
font-size: 12px;
font-weight: bold;
color: #FFFFFF;
text-shadow: rgba(0, 0, 0, 0.6) 0px -1px 0;
text-overflow: ellipsis;
text-decoration: none;
white-space: nowrap;
background: none;
-webkit-border-image: url(toolButton.png) 0 5 0 5;
}
.blueButton {
-webkit-border-image: url(blueButton.png) 0 5 0 5;
border-width: 0 5px;
}
.leftButton {
left: 6px;
right: auto;
}
#backButton {
display: none;
left: 6px;
right: auto;
padding: 0;
max-width: 55px;
border-width: 0 8px 0 14px;
-webkit-border-image: url(backButton.png) 0 8 0 14;
}
.whiteButton,
.redButton,
.grayButton {
display: block;
border-width: 0 12px;
padding: 10px;
text-align: center;
font-size: 20px;
font-weight: bold;
text-decoration: inherit;
color: inherit;
}
.whiteButton {
-webkit-border-image: url(whiteButton.png) 0 12 0 12;
text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
}
.redButton {
-webkit-border-image: url(redButton.png) 0 12 0 12;
color:#fff;
text-shadow: #7a0001 0 -1px 0;
}
.grayButton {
-webkit-border-image: url(grayButton.png) 0 12 0 12;
color: #FFFFFF;
}
/************************************************************************************************/
body > ul > li {
position: relative;
margin: 0;
border-bottom: 1px solid #E0E0E0;
padding: 8px 0 8px 10px;
font-size: 20px;
font-weight: bold;
list-style: none;
}
body > ul > li.group {
position: relative;
top: -1px;
margin-bottom: -2px;
border-top: 1px solid #7d7d7d;
border-bottom: 1px solid #999999;
padding: 1px 10px;
background: url(listGroup.png) repeat-x;
font-size: 17px;
font-weight: bold;
text-shadow: rgba(0, 0, 0, 0.4) 0 1px 0;
color: #FFFFFF;
}
body > ul > li.group:first-child {
top: 0;
border-top: none;
}
body > ul > li > a {
display: block;
margin: -8px 0 -8px -10px;
padding: 8px 32px 8px 10px;
text-decoration: none;
color: inherit;
background: url(listArrow.png) no-repeat right center;
}
a[target="_replace"] {
box-sizing: border-box;
-webkit-box-sizing: border-box;
padding-top: 25px;
padding-bottom: 25px;
font-size: 18px;
color: cornflowerblue;
background-color: #FFFFFF;
background-image: none;
}
/************************************************************************************************/
body > .dialog {
top: 0;
width: 100%;
min-height: 417px;
z-index: 2;
background: rgba(0, 0, 0, 0.8);
padding: 0;
text-align: right;
}
.dialog > fieldset {
box-sizing: border-box;
-webkit-box-sizing: border-box;
width: 100%;
margin: 0;
border: none;
border-top: 1px solid #6d84a2;
padding: 10px 6px;
background: url(toolbar.png) #7388a5 repeat-x;
}
.dialog > fieldset > h1 {
margin: 0 10px 0 10px;
padding: 0;
font-size: 20px;
font-weight: bold;
color: #FFFFFF;
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
text-align: center;
}
.dialog > fieldset > label {
position: absolute;
margin: 16px 0 0 6px;
font-size: 14px;
color: #999999;
}
/*input:not(input[type|=radio]):not(input[type|=checkbox]) {*/
input[type|=text], input[type|=password] {
box-sizing: border-box;
-webkit-box-sizing: border-box;
width: 100%;
margin: 8px 0 0 0;
padding: 6px 6px 6px 44px;
font-size: 16px;
font-weight: normal;
}
/************************************************************************************************/
body > .panel {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
padding: 10px;
background: #c8c8c8 url(pinstripes.png);
}
.panel > fieldset {
position: relative;
margin: 0 0 20px 0;
padding: 0;
background: #FFFFFF;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border: 1px solid #999999;
text-align: right;
font-size: 16px;
}
.row {
position: relative;
min-height: 42px;
border-bottom: 1px solid #999999;
-webkit-border-radius: 0;
text-align: left;
}
fieldset > .row:last-child {
border-bottom: none !important;
}
/*.row > input:not(input[type|=radio]):not(input[type|=checkbox]) {*/
.row > input[type|=text], .row > input[type|=password] {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
margin: 0;
border: none;
padding: 12px 10px 0 110px;
/* height: 42px;*/
background: none;
}
.row > input[type|=radio], .row > input[type|=checkbox] {
margin: 7px 7px 0 0;
height: 25px;
width: 25px;
}
.row > label {
position: absolute;
margin: 0 0 0 14px;
line-height: 42px;
font-weight: bold;
}
.row > span {
position: absolute;
padding: 12px 10px 0 110px;
margin: 0;
}
.row > .toggle {
position: absolute;
top: 6px;
right: 6px;
width: 100px;
height: 28px;
}
.toggle {
border: 1px solid #888888;
-webkit-border-radius: 6px;
background: #FFFFFF url(toggle.png) repeat-x;
font-size: 19px;
font-weight: bold;
line-height: 30px;
}
.toggle[toggled="true"] {
border: 1px solid #143fae;
background: #194fdb url(toggleOn.png) repeat-x;
}
.toggleOn {
display: none;
position: absolute;
width: 60px;
text-align: center;
left: 0;
top: 0;
color: #FFFFFF;
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
}
.toggleOff {
position: absolute;
width: 60px;
text-align: center;
right: 0;
top: 0;
color: #666666;
}
.toggle[toggled="true"] > .toggleOn {
display: block;
}
.toggle[toggled="true"] > .toggleOff {
display: none;
}
.thumb {
position: absolute;
top: -1px;
left: -1px;
width: 40px;
height: 28px;
border: 1px solid #888888;
-webkit-border-radius: 6px;
background: #ffffff url(thumb.png) repeat-x;
}
.toggle[toggled="true"] > .thumb {
left: auto;
right: -1px;
}
.panel > h2 {
margin: 0 0 8px 14px;
font-size: inherit;
font-weight: bold;
color: #4d4d70;
text-shadow: rgba(255, 255, 255, 0.75) 2px 2px 0;
}
/************************************************************************************************/
#preloader {
display: none;
background-image: url(loading.gif), url(selection.png),
url(blueButton.png), url(listArrowSel.png), url(listGroup.png);
}

542
plugins/mobile/iui/iui.js Normal file
View file

@ -0,0 +1,542 @@
/*
Copyright (c) 2007-9, iUI Project Members
See LICENSE.txt for licensing terms
*/
(function() {
var slideSpeed = 20;
var slideInterval = 0;
var currentPage = null;
var currentDialog = null;
var currentWidth = 0;
var currentHash = location.hash;
var hashPrefix = "#_";
var pageHistory = [];
var newPageCount = 0;
var checkTimer;
var hasOrientationEvent = false;
var portraitVal = "portrait";
var landscapeVal = "landscape";
// *************************************************************************************************
window.iui =
{
animOn: true, // Slide animation with CSS transition is now enabled by default where supported
showPage: function(page, backwards)
{
if (page)
{
if (currentDialog)
{
currentDialog.removeAttribute("selected");
currentDialog = null;
}
if (hasClass(page, "dialog"))
showDialog(page);
else
{
var fromPage = currentPage;
currentPage = page;
if (fromPage)
setTimeout(slidePages, 0, fromPage, page, backwards);
else
updatePage(page, fromPage);
}
}
},
showPageById: function(pageId)
{
var page = $(pageId);
if (page)
{
var index = pageHistory.indexOf(pageId);
var backwards = index != -1;
if (backwards)
pageHistory.splice(index, pageHistory.length);
iui.showPage(page, backwards);
}
},
showPageByHref: function(href, args, method, replace, cb, bw)
{
var req = new XMLHttpRequest();
req.onerror = function()
{
if (cb)
cb(false);
};
req.onreadystatechange = function()
{
if (req.readyState == 4)
{
if (replace)
replaceElementWithSource(replace, req.responseText);
else
{
var frag = document.createElement("div");
frag.innerHTML = req.responseText;
iui.insertPages(frag.childNodes, bw);
}
if (cb)
setTimeout(cb, 1000, true);
}
};
if (args)
{
req.open(method || "GET", href, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.setRequestHeader("Content-Length", args.length);
req.send(args.join("&"));
}
else
{
req.open(method || "GET", href, true);
req.send(null);
}
},
insertPages: function(nodes, bw)
{
var targetPage;
for (var i = 0; i < nodes.length; ++i)
{
var child = nodes[i];
if (child.nodeType == 1)
{
if (!child.id)
child.id = "__" + (++newPageCount) + "__";
var clone = $(child.id);
if (clone)
clone.parentNode.replaceChild(child, clone);
else
document.body.appendChild(child);
if (child.getAttribute("selected") == "true" || !targetPage)
targetPage = child;
--i;
}
}
if (targetPage)
iui.showPage(targetPage, bw);
},
getSelectedPage: function()
{
for (var child = document.body.firstChild; child; child = child.nextSibling)
{
if (child.nodeType == 1 && child.getAttribute("selected") == "true")
return child;
}
},
isNativeUrl: function(href)
{
for(var i = 0; i < iui.nativeUrlPatterns.length; i++)
{
if(href.match(iui.nativeUrlPatterns[i])) return true;
}
return false;
},
nativeUrlPatterns: [
new RegExp("^http:\/\/maps.google.com\/maps\?"),
new RegExp("^mailto:"),
new RegExp("^tel:"),
new RegExp("^http:\/\/www.youtube.com\/watch\\?v="),
new RegExp("^http:\/\/www.youtube.com\/v\/"),
new RegExp("^javascript:"),
]
};
// *************************************************************************************************
addEventListener("load", function(event)
{
var page = iui.getSelectedPage();
var locPage = getPageFromLoc();
if (page)
iui.showPage(page);
if (locPage && (locPage != page))
iui.showPage(locPage);
setTimeout(preloadImages, 0);
if (typeof window.onorientationchange == "object")
{
window.onorientationchange=orientChangeHandler;
hasOrientationEvent = true;
setTimeout(orientChangeHandler, 0);
}
setTimeout(checkOrientAndLocation, 0);
checkTimer = setInterval(checkOrientAndLocation, 300);
}, false);
addEventListener("unload", function(event)
{
return;
}, false);
addEventListener("click", function(event)
{
var link = findParent(event.target, "a");
if (link)
{
function unselect() { link.removeAttribute("selected"); }
if (link.href && link.hash && link.hash != "#" && !link.target)
{
link.setAttribute("selected", "true");
iui.showPage($(link.hash.substr(1)));
setTimeout(unselect, 500);
}
else if (link == $("backButton"))
history.back();
else if (link.getAttribute("type") == "submit")
{
var form = findParent(link, "form");
if (form.target == "_self")
{
form.submit();
return; // return so we don't preventDefault
}
submitForm(form);
}
else if (link.getAttribute("type") == "cancel")
cancelDialog(findParent(link, "form"));
else if (link.target == "_replace")
{
link.setAttribute("selected", "progress");
iui.showPageByHref(link.href, null, null, link, unselect);
}
else if (iui.isNativeUrl(link.href))
{
return;
}
else if (link.target == "_webapp")
{
location.href = link.href;
}
else if (!link.target)
{
link.setAttribute("selected", "progress");
var bw = link.getAttribute("backwards");
iui.showPageByHref(link.href, null, null, null, unselect, bw);
}
else
return;
event.preventDefault();
}
}, true);
addEventListener("click", function(event)
{
var div = findParent(event.target, "div");
if (div && hasClass(div, "toggle"))
{
div.setAttribute("toggled", div.getAttribute("toggled") != "true");
event.preventDefault();
}
}, true);
function getPageFromLoc()
{
var page;
var result = location.hash.match(/#_([^\?_]+)/);
if (result)
page = result[1];
if (page)
page = $(page);
return page;
}
function orientChangeHandler()
{
var orientation=window.orientation;
switch(orientation)
{
case 0:
setOrientation(portraitVal);
break;
case 90:
case -90:
setOrientation(landscapeVal);
break;
}
}
function checkOrientAndLocation()
{
if (!hasOrientationEvent)
{
if (window.innerWidth != currentWidth)
{
currentWidth = window.innerWidth;
var orient = currentWidth == 320 ? portraitVal : landscapeVal;
setOrientation(orient);
}
}
if (location.hash != currentHash)
{
var pageId = location.hash.substr(hashPrefix.length);
iui.showPageById(pageId);
}
}
function setOrientation(orient)
{
document.body.setAttribute("orient", orient);
setTimeout(scrollTo, 100, 0, 1);
}
function showDialog(page)
{
currentDialog = page;
page.setAttribute("selected", "true");
if (hasClass(page, "dialog") && !page.target)
showForm(page);
}
function showForm(form)
{
form.onsubmit = function(event)
{
event.preventDefault();
submitForm(form);
};
form.onclick = function(event)
{
if (event.target == form && hasClass(form, "dialog"))
cancelDialog(form);
};
}
function cancelDialog(form)
{
form.removeAttribute("selected");
}
function updatePage(page, fromPage)
{
if (!page.id)
page.id = "__" + (++newPageCount) + "__";
location.hash = currentHash = hashPrefix + page.id;
pageHistory.push(page.id);
var pageTitle = $("pageTitle");
if (page.title)
pageTitle.innerHTML = page.title;
if (page.localName.toLowerCase() == "form" && !page.target)
showForm(page);
var backButton = $("backButton");
if (backButton)
{
var prevPage = $(pageHistory[pageHistory.length-2]);
if (prevPage && !page.getAttribute("hideBackButton"))
{
backButton.style.display = "inline";
backButton.innerHTML = prevPage.title ? prevPage.title : "Back";
}
else
backButton.style.display = "none";
}
var backButton = $("myBackButton");
if (backButton)
{
var label = page.getAttribute("myBackLabel");
if (label)
{
backButton.style.display = "inline";
backButton.innerHTML = label;
backButton.href = page.getAttribute("myBackHref");
//backButton.target = page.getAttribute("myBackTarget");
target = page.getAttribute("myBackTarget");
if (target == null)
backButton.target = '';
else
backButton.target = target;
backButton.setAttribute("backwards", "true");
}
else
backButton.style.display = "none";
}
}
function slidePages(fromPage, toPage, backwards)
{
var axis = (backwards ? fromPage : toPage).getAttribute("axis");
clearInterval(checkTimer);
if (canDoSlideAnim() && axis != 'y')
{
slide2(fromPage, toPage, backwards, slideDone);
}
else
{
slide1(fromPage, toPage, backwards, axis, slideDone);
}
function slideDone()
{
if (!hasClass(toPage, "dialog"))
fromPage.removeAttribute("selected");
checkTimer = setInterval(checkOrientAndLocation, 300);
setTimeout(updatePage, 0, toPage, fromPage);
fromPage.removeEventListener('webkitTransitionEnd', slideDone, false);
}
}
function canDoSlideAnim()
{
return (iui.animOn) && (typeof WebKitCSSMatrix == "object");
}
function slide1(fromPage, toPage, backwards, axis, cb)
{
if (axis == "y")
(backwards ? fromPage : toPage).style.top = "100%";
else
toPage.style.left = "100%";
scrollTo(0, 1);
toPage.setAttribute("selected", "true");
var percent = 100;
slide();
var timer = setInterval(slide, slideInterval);
function slide()
{
percent -= slideSpeed;
if (percent <= 0)
{
percent = 0;
clearInterval(timer);
cb();
}
if (axis == "y")
{
backwards
? fromPage.style.top = (100-percent) + "%"
: toPage.style.top = percent + "%";
}
else
{
fromPage.style.left = (backwards ? (100-percent) : (percent-100)) + "%";
toPage.style.left = (backwards ? -percent : percent) + "%";
}
}
}
function slide2(fromPage, toPage, backwards, cb)
{
toPage.style.webkitTransitionDuration = '0ms'; // Turn off transitions to set toPage start offset
// fromStart is always 0% and toEnd is always 0%
// iPhone won't take % width on toPage
var toStart = 'translateX(' + (backwards ? '-' : '') + window.innerWidth + 'px)';
var fromEnd = 'translateX(' + (backwards ? '100%' : '-100%') + ')';
toPage.style.webkitTransform = toStart;
toPage.setAttribute("selected", "true");
toPage.style.webkitTransitionDuration = ''; // Turn transitions back on
function startTrans()
{
fromPage.style.webkitTransform = fromEnd;
toPage.style.webkitTransform = 'translateX(0%)'; //toEnd
}
fromPage.addEventListener('webkitTransitionEnd', cb, false);
setTimeout(startTrans, 0);
}
function preloadImages()
{
var preloader = document.createElement("div");
preloader.id = "preloader";
document.body.appendChild(preloader);
}
function submitForm(form)
{
iui.showPageByHref(form.action || "POST", encodeForm(form), form.method);
}
function encodeForm(form)
{
function encode(inputs)
{
for (var i = 0; i < inputs.length; ++i)
{
if (inputs[i].name)
args.push(inputs[i].name + "=" + escape(inputs[i].value));
}
}
var args = [];
encode(form.getElementsByTagName("input"));
encode(form.getElementsByTagName("textarea"));
encode(form.getElementsByTagName("select"));
return args;
}
function findParent(node, localName)
{
while (node && (node.nodeType != 1 || node.localName.toLowerCase() != localName))
node = node.parentNode;
return node;
}
function hasClass(self, name)
{
var re = new RegExp("(^|\\s)"+name+"($|\\s)");
return re.exec(self.getAttribute("class")) != null;
}
function replaceElementWithSource(replace, source)
{
var page = replace.parentNode;
var parent = replace;
while (page.parentNode != document.body)
{
page = page.parentNode;
parent = parent.parentNode;
}
var frag = document.createElement(parent.localName);
frag.innerHTML = source;
page.removeChild(parent);
while (frag.firstChild)
page.appendChild(frag.firstChild);
}
function $(id) { return document.getElementById(id); }
function ddd() { console.log.apply(console, arguments); }
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

View file

@ -0,0 +1,58 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Tiny Tiny RSS</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<link rel="apple-touch-icon" href="iui/iui-logo-touch-icon.png" />
<meta name="apple-touch-fullscreen" content="YES" />
<style type="text/css" media="screen">@import "iui/iui.css";</style>
<script type="application/x-javascript" src="iui/iui.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<script type="text/javascript">
function do_login() {
var f = document.forms['login'];
f.submit();
}
</script>
<body>
<div class="toolbar">
<h1 id="pageTitle"></h1>
<a id="backButton" class="button" href="#"></a>
<a class="button blueButton" onclick='do_login()'><?php echo __('Log in') ?></a>
</div>
<form target="_self" title="Login" id="login" class="panel" name="login" selected="true"
action="../../public.php?return=<?php echo htmlspecialchars($_SERVER["REQUEST_URI"]) ?>"
method="post">
<input type="hidden" name="op" value="login">
<fieldset>
<div class="row">
<label><?php echo __("Login:") ?></label>
<input type="text" autocapitalize="off" name="login">
</div>
<div class="row">
<label><?php echo __("Password:") ?></label>
<input type="password" name="password">
</div>
</fieldset>
<div align='center'><a target='_self' href='<?php echo get_self_url_prefix() ?>/index.php?mobile=false'>
<?php echo __("Open regular version") ?></a>
</form>
</body>
</html>

15
plugins/mobile/logout.php Normal file
View file

@ -0,0 +1,15 @@
<?php
$basedir = dirname(dirname(dirname(__FILE__)));
set_include_path(
dirname(__FILE__) . PATH_SEPARATOR .
$basedir . PATH_SEPARATOR .
"$basedir/include" . PATH_SEPARATOR .
get_include_path());
require_once "mobile-functions.php";
logout_user();
header("Location: index.php");
?>

View file

@ -0,0 +1,539 @@
<?php
require_once "functions.php";
require_once "sessions.php";
require_once "version.php";
require_once "db-prefs.php";
define('TTRSS_SESSION_NAME', 'ttrss_m_sid');
/* TODO replace with interface to db-prefs */
function mobile_pref_toggled($link, $id) {
if (get_pref($link, "_MOBILE_$id"))
return "true";
else
return "";
}
function mobile_get_pref($link, $id) {
//return $_SESSION["mobile-prefs"][$id];
return get_pref($link, "_MOBILE_$id");
}
function mobile_set_pref($link, $id, $value) {
//$_SESSION["mobile-prefs"][$id] = $value;
return set_pref($link, "_MOBILE_$id", $value);
}
function mobile_feed_has_icon($id) {
return file_exists("../../".ICONS_DIR."/$id.ico");
}
function render_flat_feed_list($link, $offset) {
$owner_uid = $_SESSION["uid"];
$limit = 0;
if (!$offset) $offset = 0;
if (mobile_get_pref($link, "SORT_FEEDS_UNREAD")) {
$order_by = "unread DESC, title";
} else {
$order_by = "title";
}
if ($limit > 0) {
$limit_qpart = "LIMIT $limit OFFSET $offset";
} else {
$limit_qpart = "";
}
$result = db_query($link, "SELECT id,
title,
(SELECT COUNT(id) FROM ttrss_entries,ttrss_user_entries
WHERE feed_id = ttrss_feeds.id AND unread = true
AND ttrss_user_entries.ref_id = ttrss_entries.id
AND owner_uid = '$owner_uid') AS unread
FROM ttrss_feeds
WHERE
ttrss_feeds.owner_uid = '$owner_uid'
ORDER BY $order_by $limit_qpart");
if (!$offset) print '<ul id="home" title="'.__('Home').'" selected="true"
myBackLabel="'.__('Logout').'" myBackHref="logout.php" myBackTarget="_self">';
// print "<li><a href='#cat-actions'>".__('Actions...')."</a></li>";
$num_feeds = 0;
while ($line = db_fetch_assoc($result)) {
$id = $line["id"];
$unread = $line["unread"];
// $unread = rand(0, 100);
if ($unread > 0) {
$line["title"] = $line["title"] . " ($unread)";
$class = '';
} else {
$class = 'oldItem';
}
if (mobile_feed_has_icon($id)) {
$icon_url = "../../".ICONS_URL."/$id.ico";
} else {
$icon_url = "../../images/blank_icon.gif";
}
if ($unread > 0 || !mobile_get_pref($link, "HIDE_READ")) {
print "<li class='$class'><a href='feed.php?id=$id'>" .
"<img class='tinyIcon' src='$icon_url'/>".
$line["title"] . "</a></li>";
}
++$num_feeds;
}
/* $next_offset = $offset + $num_feeds;
print "<li><a href=\"home.php?skip=$next_offset\"
target=\"_replace\">Show more feeds...</a></li>"; */
if (!$offset) print "</ul>";
}
function render_category($link, $cat_id, $offset) {
$owner_uid = $_SESSION["uid"];
if ($cat_id >= 0) {
if ($cat_id != 0) {
$cat_query = "cat_id = '$cat_id'";
} else {
$cat_query = "cat_id IS NULL";
}
if (mobile_get_pref($link, "SORT_FEEDS_UNREAD")) {
$order_by = "unread DESC, title";
} else {
$order_by = "title";
}
$result = db_query($link, "SELECT id,
title,
(SELECT COUNT(id) FROM ttrss_entries,ttrss_user_entries
WHERE feed_id = ttrss_feeds.id AND unread = true
AND ttrss_user_entries.ref_id = ttrss_entries.id
AND owner_uid = '$owner_uid') as unread
FROM ttrss_feeds
WHERE
ttrss_feeds.owner_uid = '$owner_uid' AND
$cat_query
ORDER BY $order_by");
$title = getCategoryTitle($link, $cat_id);
print "<ul id='cat-$cat_id' title='$title' myBackLabel='".__("Home")."'
myBackHref='home.php'>";
// print "<li><a href='#cat-actions'>".__('Actions...')."</a></li>";
while ($line = db_fetch_assoc($result)) {
$id = $line["id"];
$unread = $line["unread"];
// $unread = rand(0, 100);
if ($unread > 0) {
$line["title"] = $line["title"] . " ($unread)";
$class = '';
} else {
$class = 'oldItem';
}
if (mobile_feed_has_icon($id)) {
$icon_url = "../../".ICONS_URL."/$id.ico";
} else {
$icon_url = "../../images/blank_icon.gif";
}
if ($unread > 0 || !mobile_get_pref($link, "HIDE_READ")) {
print "<li class='$class'><a href='feed.php?id=$id&cat=$cat_id'>" .
"<img class='tinyIcon' src='$icon_url'/>".
$line["title"] . "</a></li>";
}
}
print "</ul>";
} else if ($cat_id == -1) {
$title = __('Special');
print "<ul id='cat--1' title='$title' myBackLabel='".__("Home")."'
myBackHref='home.php'>";
foreach (array(-4, -3, -1, -2, 0) as $id) {
$title = getFeedTitle($link, $id);
$unread = getFeedUnread($link, $id, false);
$icon = getFeedIcon($id);
if ($unread > 0) {
$title = $title . " ($unread)";
$class = '';
} else {
$class = 'oldItem';
}
if ($unread > 0 || !mobile_get_pref($link, "HIDE_READ")) {
print "<li class='$class'>
<a href='feed.php?id=$id&cat=-1'>
<img class='tinyIcon' src='../$icon'/>$title</a></li>";
}
}
print "</ul>";
} else if ($cat_id == -2) {
$title = __('Labels');
print "<ul id='cat--2' title='$title' myBackLabel='".__("Home")."'
myBackHref='home.php'>";
$result = db_query($link, "SELECT id, caption FROM ttrss_labels2
WHERE owner_uid = '$owner_uid'");
$label_data = array();
while ($line = db_fetch_assoc($result)) {
$id = -$line["id"] - 11;
$unread = getFeedUnread($link, $id);
$title = $line["caption"];
if ($unread > 0) {
$title = $title . " ($unread)";
$class = '';
} else {
$class = 'oldItem';
}
if ($unread > 0 || !mobile_get_pref($link, "HIDE_READ")) {
print "<li class='$class'>
<a href='feed.php?id=$id&cat=-2'>$title</a></li>";
}
}
print "</ul>";
}
}
function render_categories_list($link) {
$owner_uid = $_SESSION["uid"];
$cat_browse = mobile_get_pref($link, "BROWSE_CATS");
print '<ul id="home" title="'.__('Home').'" selected="true"
myBackLabel="'.__('Logout').'" myBackHref="logout.php" myBackTarget="_self">';
// print "<li><a href='#searchForm'>Search...</a></li>";
foreach (array(-1, -2) as $id) {
$title = getCategoryTitle($link, $id);
$unread = getFeedUnread($link, $id, true);
if ($unread > 0) {
$title = $title . " ($unread)";
$class = '';
} else {
$class = 'oldItem';
}
if ($cat_browse)
print "<li class='$class'><a href='cat.php?id=$id'>$title</a></li>";
else
print "<li class='$class'><a href='feed.php?id=$id&is_cat=true'>$title</a></li>";
}
$result = db_query($link, "SELECT
ttrss_feed_categories.id,
ttrss_feed_categories.title,
COUNT(ttrss_feeds.id) AS num_feeds
FROM ttrss_feed_categories, ttrss_feeds
WHERE ttrss_feed_categories.owner_uid = $owner_uid
AND ttrss_feed_categories.id = cat_id
GROUP BY ttrss_feed_categories.id,
ttrss_feed_categories.title
ORDER BY ttrss_feed_categories.title");
while ($line = db_fetch_assoc($result)) {
if ($line["num_feeds"] > 0) {
$unread = getFeedUnread($link, $line["id"], true);
$id = $line["id"];
if ($unread > 0) {
$line["title"] = $line["title"] . " ($unread)";
$class = '';
} else {
$class = 'oldItem';
}
if ($unread > 0 || !mobile_get_pref($link, "HIDE_READ")) {
if ($cat_browse)
print "<li class='$class'><a href='cat.php?id=$id'>" .
$line["title"] . "</a></li>";
else
print "<li class='$class'><a href='feed.php?id=$id&is_cat=true'>".
$line["title"] . "</a></li>";
}
}
}
$result = db_query($link, "SELECT COUNT(*) AS nf FROM ttrss_feeds WHERE
cat_id IS NULL and owner_uid = '$owner_uid'");
$num_feeds = db_fetch_result($result, 0, "nf");
if ($num_feeds > 0) {
$unread = getFeedUnread($link, 0, true);
$title = "Uncategorized";
if ($unread > 0) {
$title = "$title ($unread)";
$class = '';
} else {
$class = 'oldItem';
}
if ($unread > 0 || !mobile_get_pref($link, "HIDE_READ")) {
if ($cat_browse)
print "<li class='$class'><a href='cat.php?id=0'>$title</a></li>";
else
print "<li class='$class'><a href='feed.php?id=0&is_cat=true'>$title</a></li>";
}
}
print "</ul>";
}
function render_headlines_list($link, $feed_id, $cat_id, $offset, $search,
$is_cat = false) {
$feed_id = $feed_id;
$limit = 15;
$filter = '';
if (!mobile_get_pref($link, "HIDE_READ"))
$view_mode = "all_articles";
else
$view_mode = 'adaptive';
if ($search) {
$search_mode = 'this_feed';
} else {
$search_mode = '';
}
$qfh_ret = queryFeedHeadlines($link, $feed_id, $limit,
$view_mode, $is_cat, $search, $search_mode,
"score DESC, date_entered ".(mobile_get_pref($link, 'REVERSE_HEADLINES') ? 'ASC' : 'DESC'), $offset);
$result = $qfh_ret[0];
$feed_title = $qfh_ret[1];
if (!$offset) {
print "<form id=\"searchForm-$feed_id-$cat_id\" class=\"dialog\" method=\"POST\"
action=\"feed.php\">
<input type=\"hidden\" name=\"id\" value=\"$feed_id\">
<input type=\"hidden\" name=\"cat\" value=\"$cat_id\">
<fieldset>
<h1>Search</h1>
<a class=\"button leftButton\" type=\"cancel\">Cancel</a>
<a class=\"button blueButton\" type=\"submit\">Search</a>
<label>Search:</label>
<input id=\"search\" type=\"text\" name=\"search\"/>
</fieldset>
</form>";
if ($cat_id) {
$cat_title = getCategoryTitle($link, $cat_id);
print "<ul id=\"feed-$feed_id\" title=\"$feed_title\" selected=\"true\"
myBackLabel='$cat_title' myBackHref='cat.php?id=$cat_id'>";
} else {
print "<ul id=\"feed-$feed_id\" title=\"$feed_title\" selected=\"true\"
myBackLabel='".__("Home")."' myBackHref='home.php'>";
}
print "<li><a href='#searchForm-$feed_id-$cat_id'>Search...</a></li>";
}
$num_headlines = 0;
while ($line = db_fetch_assoc($result)) {
$id = $line["id"];
$real_feed_id = $line["feed_id"];
if (sql_bool_to_bool($line["unread"])) {
$class = '';
} else {
$class = 'oldItem';
}
if (mobile_feed_has_icon($real_feed_id)) {
$icon_url = "../../".ICONS_URL."/$real_feed_id.ico";
} else {
$icon_url = "../../images/blank_icon.gif";
}
print "<li class='$class'><a href='article.php?id=$id&feed=$feed_id&cat=$cat_id&is_cat=$is_cat'>
<img class='tinyIcon' src='$icon_url'>";
print $line["title"];
print "</a></li>";
++$num_headlines;
}
if ($num_headlines == 0 && $search) {
$articles_url = "feed.php?id=$feed_id&cat=$cat_id&skip=$next_offset";
print "<li><a href=\"$articles_url\">" . __("Nothing found (click to reload feed).") . "</a></li>";
}
// print "<a target='_replace' href='feed.php?id=$feed_id&cat=$cat_id&skip=0'>Next $limit articles...</a>";
$next_offset = $offset + $num_headlines;
$num_unread = getFeedUnread($link, $feed_id, $is_cat);
/* FIXME needs normal implementation */
if ($num_headlines > 0 && ($num_unread == 0 || $num_unread > $next_offset)) {
if ($is_cat) {
$articles_url = "feed.php?id=$feed_id&skip=$next_offset".
"&search=$search&is_cat=true";
} else {
$articles_url = "feed.php?id=$feed_id&cat=$cat_id&skip=$next_offset".
"&search=$search";
}
print "<li><a href=\"$articles_url\"
target=\"_replace\">Get more articles...</a></li>";
}
if (!$offset) print "</ul>";
}
function render_article($link, $id, $feed_id, $cat_id, $is_cat) {
$query = "SELECT title,link,content,feed_id,comments,int_id,
marked,unread,published,
".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
author
FROM ttrss_entries,ttrss_user_entries
WHERE id = '$id' AND ref_id = id AND owner_uid = " .
$_SESSION["uid"] ;
$result = db_query($link, $query);
if (db_num_rows($result) != 0) {
$line = db_fetch_assoc($result);
$tmp_result = db_query($link, "UPDATE ttrss_user_entries
SET unread = false,last_read = NOW()
WHERE ref_id = '$id'
AND owner_uid = " . $_SESSION["uid"]);
$updated_fmt = make_local_datetime($link, $line['updated'], false);
$title = $line["title"];
$article_link = $line["link"];
if (!$is_cat)
$feed_title = getFeedTitle($link, $feed_id);
else
$feed_title = getCategoryTitle($link, $feed_id);
print "<div class=\"panel\" id=\"article-$id\" title=\"$title\"
selected=\"true\"
myBackLabel='$feed_title' myBackHref='feed.php?id=$feed_id&cat=$cat_id&is_cat=$is_cat'>";
if ($line['feed_id'] != $feed_id) {
$real_feed_title = getFeedTitle($link, $line['feed_id']);
$real_feed_id = $line['feed_id'];
$feed_link = "(<a href=\"feed.php?id=$real_feed_id\">$real_feed_title</a>)";
}
// print "<fieldset>";
print "<div style='float : right'>($updated_fmt)</div>";
print "<h2><a target='_blank' href='$article_link'>$title</a> $feed_link</h2>";
print "<hr>";
/* print "<div class=\"row\">";
print "<label id='title'><a target='_blank' href='$article_link'>$title</a></label>";
print "</div>"; */
$is_starred = (sql_bool_to_bool($line["marked"])) ? "true" : "false";
$is_published = (sql_bool_to_bool($line["published"])) ? "true" : "false";
//print "<div class=\"row\">";
//print "<label id='updated'>Updated:</label>";
//print "<input type='text' enabled='false' name='updated' disabled value='$updated_fmt'/>";
//print "</div>";
// print "</fieldset>";
$content = sanitize($link, $line["content"]);
$content = preg_replace("/href=/i", "target=\"_blank\" href=", $content);
if (!mobile_get_pref($link, "SHOW_IMAGES")) {
$content = preg_replace('/<img[^>]+>/is', '', $content);
}
print "<p>$content</p>";
print "<div class='nav'>
<label>Navigation</label>
<div class='button left' onclick='goPrev($id, $feed_id, this)'>Prev</div>
<div class='button right' onclick='goNext($id, $feed_id, this)'>Next</div>
</div>";
print "<fieldset>";
print "<div class=\"row\">
<label>Starred</label>
<div class=\"toggle\" onclick=\"toggleMarked($id, this)\" toggled=\"$is_starred\"><span class=\"thumb\"></span><span class=\"toggleOn\">ON</span><span class=\"toggleOff\">OFF</span></div>
</div>";
print "<div class=\"row\">
<label>Published</label>
<div class=\"toggle\" onclick=\"togglePublished($id, this)\" toggled=\"$is_published\"><span class=\"thumb\"></span><span class=\"toggleOn\">ON</span><span class=\"toggleOff\">OFF</span></div>
</div>";
print "<div class=\"row\">
<label>Unread</label>
<div class=\"toggle\" onclick=\"toggleUnread($id, this)\" toggled=\"$is_unread\"><span class=\"thumb\"></span><span class=\"toggleOn\">ON</span><span class=\"toggleOff\">OFF</span></div>
</div>";
print "</fieldset>";
print "</div>";
}
}
?>

38
plugins/mobile/mobile.css Normal file
View file

@ -0,0 +1,38 @@
div.nav {
height: 40px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
background-color: #ffffff;
border: 1px solid #999999;
text-align: center;
margin-bottom: 1em;
}
div.nav label {
line-height: 40px;
color: black;
font-weight: bold;
}
div.nav .button {
position: static;
margin: 5px 10px;
-webkit-border-image: url(../lib/iui/whiteButton.png) 0 12 0 12;
text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
color: black;
cursor: pointer; /* On a touch screen ? */
}
div.nav .button.left {
float: left;
}
div.nav .button.right {
float: right;
}
ul li a.read {
color: #666666;
}
ul li span.browse {
color : #909090;
text-align : right;
float : right;
}

163
plugins/mobile/mobile.js Normal file
View file

@ -0,0 +1,163 @@
var backend = "backend.php";
function toggleMarked(id, elem) {
var toggled = false;
if (elem.getAttribute("toggled") == "true") {
toggled = 1;
} else {
toggled = 0;
}
var query = "op=toggleMarked&id=" + id + "&mark=" + toggled;
new Ajax.Request(backend, {
parameters: query,
onComplete: function (transport) {
//
} });
}
function togglePublished(id, elem) {
var toggled = false;
if (elem.getAttribute("toggled") == "true") {
toggled = 1;
} else {
toggled = 0;
}
var query = "op=togglePublished&id=" + id + "&pub=" + toggled;
new Ajax.Request(backend, {
parameters: query,
onComplete: function (transport) {
//
} });
}
function toggleUnread(id, elem) {
var toggled = false;
if (elem.getAttribute("toggled") == "true") {
toggled = 1;
} else {
toggled = 0;
}
var query = "op=toggleUnread&id=" + id + "&unread=" + toggled;
new Ajax.Request(backend, {
parameters: query,
onComplete: function (transport) {
//
} });
}
function setPref(elem) {
var toggled = false;
var id = elem.id;
if (elem.getAttribute("toggled") == "true") {
toggled = 1;
} else {
toggled = 0;
}
var query = "op=setPref&id=" + id + "&to=" + toggled;
new Ajax.Request(backend, {
parameters: query,
onComplete: function (transport) {
//
} });
}
// Go directly to another item in the same feed
function goToSibling(article_id, feed_id, link, step) {
var links = linksInFeed(feed_id);
for (var i=0 ; i<links.length ; i++) {
var re = new RegExp(".*article\\.php\\?id="+article_id+"&.*");
if (!re.test(links[i].href)) continue;
// here, we've found the current article
var index = i + step;
if (index < 0) {
markAsRead(feed_id);
iui.showPage($("feed-"+feed_id), true);
return false;
}
if (index >= links.length) {
showRestOfFeed(feed_id);
return false;
}
console.log(links[index]);
var match = links[index].href.match(/.*article\.php\?(.*)/);
var qs = match[1];
var backwards = false;
if (step < 0) backwards = true;
link.setAttribute("selected", "progress");
function unselect() { link.removeAttribute("selected"); }
iui.showPageByHref("article.php?"+qs, null, null, null, unselect, backwards);
return false;
}
return false;
}
function goPrev(article_id, feed_id, link) {
return goToSibling(article_id, feed_id, link, -1);
}
function goNext(article_id, feed_id, link) {
return goToSibling(article_id, feed_id, link, 1);
}
// Get all the links in the feed. The all_links variable includes the "get more article" link
function linksInFeed(feed_id, all_links) {
var feed_content = $("feed-"+feed_id);
var links_raw = feed_content.getElementsByTagName("a");
if (all_links) return links_raw;
var links = [];
// filter the array to remove the "get more articles" link
// and the "search" link (which is always first)
for (var i=1 ; i<links_raw.length ; i++) {
if (links_raw[i].href.match(/.*article\.php\?id=.*/)) {
links.push(links_raw[i]);
}
}
return links;
}
// Adds the "read" class to all read links in the feed
function markAsRead(feed_id) {
var links = linksInFeed(feed_id);
for (var j=0 ; j<links.length ; j++) {
var match = links[j].href.match(/.*article\.php\?id=(\d+)&.*/);
if ($("article-"+match[1])) {
links[j].className = "read";
}
}
}
// Go the the articles list and expand the "get more articles" link
function showRestOfFeed(feed_id) {
var links_raw = linksInFeed(feed_id, true);
var lastlink = links_raw[links_raw.length - 1];
if (lastlink.target == "_replace") {
// It's a "get more articles" link
iui.showPage($("feed-"+feed_id), true);
// Mark old items a "read"
markAsRead(feed_id);
// Simulate click on the "get more articles" link
lastlink.setAttribute("selected", "progress");
function unselect() { lastlink.removeAttribute("selected"); }
setTimeout(window.scrollTo, 0, 0, 1000);
iui.showPageByHref(lastlink.href, null, null, lastlink, unselect);
} else {
iui.showPage($("home"), true);
}
}

64
plugins/mobile/prefs.php Normal file
View file

@ -0,0 +1,64 @@
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
header('Content-Type: text/html; charset=utf-8');
define('MOBILE_VERSION', true);
$basedir = dirname(dirname(dirname(__FILE__)));
set_include_path(
dirname(__FILE__) . PATH_SEPARATOR .
$basedir . PATH_SEPARATOR .
"$basedir/include" . PATH_SEPARATOR .
get_include_path());
$basedir = dirname(dirname(__FILE__));
require_once "config.php";
require_once "mobile-functions.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
init_connection($link);
login_sequence($link, true);
?>
<div class="panel" id="prefs" selected="yes" title="Preferences"
myBackLabel="<?php echo __('Home') ?>" myBackHref="home.php">
<fieldset>
<div class="row">
<label><?php echo __('Enable categories') ?></label>
<div class="toggle" id="ENABLE_CATS" onclick="setPref(this)" toggled="<?php echo mobile_pref_toggled($link, "ENABLE_CATS") ?>"><span class="thumb"></span><span class="toggleOn"><?php echo __('ON') ?></span><span class="toggleOff"><?php echo __('OFF') ?></span></div>
</div>
<div class="row">
<label><?php echo __('Browse categories like folders') ?></label>
<div class="toggle" id="BROWSE_CATS" onclick="setPref(this)" toggled="<?php echo mobile_pref_toggled($link, "BROWSE_CATS") ?>"><span class="thumb"></span><span class="toggleOn"><?php echo __('ON') ?></span><span class="toggleOff"><?php echo __('OFF') ?></span></div>
</div>
<div class="row">
<label><?php echo __('Show images in posts') ?></label>
<div class="toggle" id="SHOW_IMAGES" onclick="setPref(this)" toggled="<?php echo mobile_pref_toggled($link, "SHOW_IMAGES") ?>"><span class="thumb"></span><span class="toggleOn"><?php echo __('ON') ?></span><span class="toggleOff"><?php echo __('OFF') ?></span></div>
</div>
<div class="row">
<label><?php echo __('Hide read articles and feeds') ?></label>
<div class="toggle" id="HIDE_READ" onclick="setPref(this)" toggled="<?php echo mobile_pref_toggled($link, "HIDE_READ") ?>"><span class="thumb"></span><span class="toggleOn"><?php echo __('ON') ?></span><span class="toggleOff"><?php echo __('OFF') ?></span></div>
</div>
<div class="row">
<label><?php echo __('Sort feeds by unread count') ?></label>
<div class="toggle" id="SORT_FEEDS_UNREAD" onclick="setPref(this)" toggled="<?php echo mobile_pref_toggled($link, "SORT_FEEDS_UNREAD") ?>"><span class="thumb"></span><span class="toggleOn"><?php echo __('ON') ?></span><span class="toggleOff"><?php echo __('OFF') ?></span></div>
</div>
<div class="row">
<label><?php echo __('Reverse headline order (oldest first)') ?></label>
<div class="toggle" id="REVERSE_HEADLINES" onclick="setPref(this)" toggled="<?php echo mobile_pref_toggled($link, "REVERSE_HEADLINES") ?>"><span class="thumb"></span><span class="toggleOn"><?php echo __('ON') ?></span><span class="toggleOff"><?php echo __('OFF') ?></span></div>
</div>
</fieldset>