2012-12-24 23:01:25 -08:00
//
// TrainerViewController . m
// NewsBlur
//
// Created by Samuel Clay on 12 / 24 / 12.
// Copyright ( c ) 2012 NewsBlur . All rights reserved .
//
# import "TrainerViewController.h"
# import "StringHelper.h"
2013-02-07 11:46:44 -08:00
# import "Utilities.h"
2013-10-02 16:05:22 -07:00
# import "AFNetworking.h"
2014-02-12 20:09:37 -08:00
# import "StoriesCollection.h"
2012-12-24 23:01:25 -08:00
@ implementation TrainerViewController
@ synthesize closeButton ;
@ synthesize webView ;
@ synthesize navBar ;
@ synthesize appDelegate ;
2012-12-27 00:15:26 -08:00
@ synthesize feedTrainer ;
@ synthesize storyTrainer ;
2013-10-02 16:05:22 -07:00
@ synthesize feedLoaded ;
2012-12-24 23:01:25 -08:00
- ( id ) initWithNibName : ( NSString * ) nibNameOrNil bundle : ( NSBundle * ) nibBundleOrNil
{
self = [ super initWithNibName : nibNameOrNil bundle : nibBundleOrNil ] ;
if ( self ) {
// Custom initialization
}
return self ;
}
- ( void ) viewDidLoad
{
[ super viewDidLoad ] ;
2020-08-29 21:19:32 -07:00
2012-12-24 23:01:25 -08:00
self . appDelegate = [ NewsBlurAppDelegate sharedAppDelegate ] ;
2013-03-02 19:15:08 -08:00
UIBarButtonItem * done = [ [ UIBarButtonItem alloc ]
initWithTitle : @ "Done Training"
2016-10-05 21:03:32 -07:00
style : UIBarButtonItemStyleDone
2013-03-02 19:15:08 -08:00
target : self
action : @ selector ( doCloseDialog : ) ] ;
self . navigationItem . rightBarButtonItem = done ;
2020-02-23 15:21:32 -08:00
self . webView . navigationDelegate = self ;
2012-12-26 02:41:13 -08:00
[ self hideGradientBackground : webView ] ;
2012-12-27 18:37:05 -08:00
[ self . webView . scrollView setDelaysContentTouches : YES ] ;
[ self . webView . scrollView setDecelerationRate : UIScrollViewDecelerationRateNormal ] ;
2016-01-24 12:01:12 -05:00
// Work around iOS 9 issue where menu doesn ' t appear the first time
// http : // stackoverflow . com / questions / 32685198 /
[ self . webView becomeFirstResponder ] ;
2012-12-26 02:41:13 -08:00
}
- ( void ) hideGradientBackground : ( UIView * ) theView
{
for ( UIView * subview in theView . subviews )
{
if ( [ subview isKindOfClass : [ UIImageView class ] ] )
subview . hidden = YES ;
[ self hideGradientBackground : subview ] ;
}
2012-12-24 23:01:25 -08:00
}
2012-12-25 12:08:17 -08:00
- ( void ) viewWillAppear : ( BOOL ) animated {
2014-09-18 11:25:51 -07:00
[ super viewWillAppear : animated ] ;
2012-12-25 19:03:50 -08:00
[ [ UIMenuController sharedMenuController ]
setMenuItems : [ NSArray arrayWithObjects :
2012-12-27 18:37:05 -08:00
[ [ UIMenuItem alloc ] initWithTitle : @ "👎 Hide" action : @ selector ( hideTitle : ) ] ,
[ [ UIMenuItem alloc ] initWithTitle : @ "👍 Focus" action : @ selector ( focusTitle : ) ] ,
2012-12-25 19:03:50 -08:00
nil ] ] ;
2014-02-12 20:09:37 -08:00
UILabel * titleLabel = ( UILabel * ) [ appDelegate makeFeedTitle : appDelegate . storiesCollection . activeFeed ] ;
2013-10-02 16:05:22 -07:00
self . navigationItem . titleView = titleLabel ;
[ MBProgressHUD hideHUDForView : self . view animated : NO ] ;
2012-12-27 18:37:05 -08:00
2013-10-02 16:05:22 -07:00
if ( ! feedLoaded ) {
MBProgressHUD * HUD = [ MBProgressHUD showHUDAddedTo : self . view animated : YES ] ;
HUD . labelText = @ "Loading trainer..." ;
2014-03-03 16:21:26 -08:00
NSString * feedId = [ self feedId ] ;
2017-04-03 16:07:01 -07:00
NSString * urlString = [ NSString stringWithFormat : @ "%@/reader/feeds_trainer?feed_id=%@" ,
self . appDelegate . url , feedId ] ;
2019-08-22 12:03:39 -07:00
[ appDelegate GET : urlString parameters : nil success : ^ ( NSURLSessionDataTask * _Nonnull task , id _Nullable responseObject ) {
2017-04-03 16:07:01 -07:00
[ MBProgressHUD hideHUDForView : self . view animated : YES ] ;
2017-06-25 21:22:09 -07:00
NSArray * resultsArray = responseObject ;
2017-11-10 17:57:50 -08:00
if ( resultsArray . count ) {
NSDictionary * results = resultsArray [ 0 ] ;
NSMutableDictionary * newClassifiers = [ [ results objectForKey : @ "classifiers" ] mutableCopy ] ;
2020-08-27 15:08:46 -07:00
[ self . appDelegate . storiesCollection . activeClassifiers setObject : newClassifiers
2017-11-10 17:57:50 -08:00
forKey : feedId ] ;
2020-08-27 15:08:46 -07:00
self . appDelegate . storiesCollection . activePopularAuthors = [ results objectForKey : @ "feed_authors" ] ;
self . appDelegate . storiesCollection . activePopularTags = [ results objectForKey : @ "feed_tags" ] ;
2017-11-10 17:57:50 -08:00
}
2015-09-18 15:02:15 -07:00
[ self renderTrainer ] ;
2017-04-03 16:07:01 -07:00
} failure : ^ ( NSURLSessionDataTask * _Nullable task , NSError * _Nonnull error ) {
2015-09-18 15:02:15 -07:00
NSLog ( @ "Failed fetch trainer: %@" , error ) ;
[ self informError : @ "Could not load trainer" ] ;
dispatch_after ( dispatch_time ( DISPATCH_TIME _NOW , 1.0 * NSEC_PER _SEC ) ,
dispatch_get _main _queue ( ) , ^ ( ) {
2020-03-29 16:21:00 -07:00
if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] = = UIUserInterfaceIdiomPad ) {
2020-08-27 15:08:46 -07:00
[ self . appDelegate hidePopover ] ;
2017-04-03 16:07:01 -07:00
} else {
2020-08-29 21:19:32 -07:00
[ self . appDelegate . feedsNavigationController dismissViewControllerAnimated : YES completion : nil ] ;
2017-04-03 16:07:01 -07:00
}
} ) ;
2015-09-18 15:02:15 -07:00
} ] ;
2013-10-02 16:05:22 -07:00
} else {
[ self renderTrainer ] ;
}
}
2014-03-03 16:21:26 -08:00
- ( NSString * ) feedId {
NSString * feedId ;
2014-05-15 18:49:48 -07:00
if ( appDelegate . storiesCollection . activeFeed &&
2014-05-16 16:30:52 -07:00
! appDelegate . storiesCollection . isSocialView ) {
2014-03-03 16:21:26 -08:00
feedId = [ NSString stringWithFormat : @ "%@" ,
[ appDelegate . storiesCollection . activeFeed objectForKey : @ "id" ] ] ;
} else if ( appDelegate . activeStory ) {
feedId = [ NSString stringWithFormat : @ "%@" ,
[ appDelegate . activeStory objectForKey : @ "story_feed_id" ] ] ;
}
return feedId ;
}
2013-10-02 16:05:22 -07:00
- ( void ) renderTrainer {
2012-12-25 19:03:50 -08:00
NSString * path = [ [ NSBundle mainBundle ] bundlePath ] ;
NSURL * baseURL = [ NSURL fileURLWithPath : path ] ;
2012-12-27 18:37:05 -08:00
[ self . webView loadHTMLString : [ self makeTrainerHTML ] baseURL : baseURL ] ;
}
- ( void ) refresh {
if ( self . view . hidden || self . view . superview = = nil ) {
NSLog ( @ "Trainer hidden, ignoring redraw." ) ;
return ;
}
NSString * headerString = [ [ [ self makeTrainerSections ]
stringByReplacingOccurrencesOfString : @ "\'" withString : @ "\\'" ]
stringByReplacingOccurrencesOfString : @ "\n" withString : @ " " ] ;
NSString * jsString = [ NSString stringWithFormat : @ "document.getElementById('NB-trainer').innerHTML = '%@';" ,
headerString ] ;
2020-02-23 15:21:32 -08:00
[ self . webView evaluateJavaScript : jsString completionHandler : nil ] ;
2012-12-26 02:41:13 -08:00
2020-02-23 15:21:32 -08:00
[ self . webView evaluateJavaScript : @ "attachFastClick({skipEvent: true});" completionHandler : nil ] ;
2012-12-24 23:01:25 -08:00
}
2012-12-25 19:03:50 -08:00
- ( void ) viewDidDisappear : ( BOOL ) animated {
[ super viewDidDisappear : animated ] ;
2013-10-02 16:05:22 -07:00
[ self . webView loadHTMLString : @ "" baseURL : [ NSURL URLWithString : @ "about:blank" ] ] ;
2012-12-25 19:03:50 -08:00
[ [ UIMenuController sharedMenuController ] setMenuItems : nil ] ;
}
2012-12-24 23:01:25 -08:00
# pragma mark -
# pragma mark Story layout
2012-12-27 18:37:05 -08:00
- ( NSString * ) makeTrainerHTML {
NSString * trainerSections = [ self makeTrainerSections ] ;
2012-12-24 23:01:25 -08:00
2012-12-25 19:03:50 -08:00
int contentWidth = self . view . frame . size . width ;
NSString * contentWidthClass ;
if ( contentWidth > 700 ) {
contentWidthClass = @ "NB-ipad-wide" ;
} else if ( contentWidth > 480 ) {
contentWidthClass = @ "NB-ipad-narrow" ;
} else {
contentWidthClass = @ "NB-iphone" ;
}
// set up layout values based on iPad / iPhone
NSString * headerString = [ NSString stringWithFormat : @
"<link rel=\" stylesheet \ " type=\" text / css \ " href=\" trainer . css \ " >"
"<meta name=\" viewport \ " id=\" viewport \ " content=\" width = % i , initial - scale = 1.0 , maximum - scale = 1.0 , user - scalable = no \ "/>" ,
contentWidth ] ;
NSString * footerString = [ NSString stringWithFormat : @
"<script src=\" zepto . js \ "></script>"
"<script src=\" trainer . js \ "></script>"
"<script src=\" fastTouch . js \ "></script>" ] ;
NSString * htmlString = [ NSString stringWithFormat : @
"<html>"
"<head>%@</head>" // header string
"<body id=\" trainer \ " class=\" % @ \ ">"
2012-12-27 18:37:05 -08:00
"<div class=\" NB - trainer \ " id=\" NB - trainer \ ">%@</div>"
2012-12-25 19:03:50 -08:00
"%@" // footer
"</body>"
"</html>" ,
headerString ,
contentWidthClass ,
2012-12-27 18:37:05 -08:00
trainerSections ,
2012-12-25 19:03:50 -08:00
footerString
] ;
// NSLog ( @ "\n\n\n\nhtmlString:\n\n\n%@\n\n\n" , htmlString ) ;
return htmlString ;
2012-12-24 23:01:25 -08:00
}
2012-12-27 18:37:05 -08:00
- ( NSString * ) makeTrainerSections {
2022-08-03 21:42:28 -07:00
NSString * heading = @ "<div class=\" NB - trainer - heading \ ">What do you <b class=\" NB - trainer - heading - like \ ">👍 like</b> and <b class=\" NB - trainer - heading - dislike \ ">dislike 👎</b> about this story?</div>" ;
2012-12-27 18:37:05 -08:00
NSString * storyAuthor = self . feedTrainer ? [ self makeFeedAuthors ] : [ self makeStoryAuthor ] ;
NSString * storyTags = self . feedTrainer ? [ self makeFeedTags ] : [ self makeStoryTags ] ;
2015-09-21 13:59:31 -07:00
NSString * storyTitle = self . feedTrainer ? [ self makeFeedTitles ] : [ self makeTitle ] ;
2012-12-27 18:37:05 -08:00
NSString * storyPublisher = [ self makePublisher ] ;
NSString * htmlString = [ NSString stringWithFormat : @
2022-08-03 21:42:28 -07:00
"%@<div class=\" NB - trainer - inner \ ">"
2012-12-27 18:37:05 -08:00
" <div class=\" NB - trainer - title NB - trainer - section \ ">%@</div>"
" <div class=\" NB - trainer - author NB - trainer - section \ ">%@</div>"
" <div class=\" NB - trainer - tags NB - trainer - section \ ">%@</div>"
" <div class=\" NB - trainer - publisher NB - trainer - section \ ">%@</div>"
"</div>" ,
2022-08-03 21:42:28 -07:00
heading ,
2012-12-27 18:37:05 -08:00
storyTitle ,
storyAuthor ,
storyTags ,
storyPublisher ] ;
return htmlString ;
}
2012-12-27 00:15:26 -08:00
- ( NSString * ) makeStoryAuthor {
2012-12-24 23:01:25 -08:00
NSString * feedId = [ NSString stringWithFormat : @ "%@" , [ appDelegate . activeStory
objectForKey : @ "story_feed_id" ] ] ;
NSString * storyAuthor = @ "" ;
2012-12-27 00:15:26 -08:00
2012-12-24 23:01:25 -08:00
if ( [ [ appDelegate . activeStory objectForKey : @ "story_authors" ] class ] ! = [ NSNull class ] &&
[ [ appDelegate . activeStory objectForKey : @ "story_authors" ] length ] ) {
NSString * author = [ NSString stringWithFormat : @ "%@" ,
[ appDelegate . activeStory objectForKey : @ "story_authors" ] ] ;
if ( author && [ author class ] ! = [ NSNull class ] ) {
2014-02-12 20:09:37 -08:00
int authorScore = [ [ [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
2012-12-24 23:01:25 -08:00
objectForKey : @ "authors" ]
objectForKey : author ] intValue ] ;
2012-12-25 19:03:50 -08:00
storyAuthor = [ NSString stringWithFormat : @ "<div class=\" NB - trainer - section - inner \ ">"
" <div class=\" NB - trainer - section - title \ ">Story Authors</div>"
" <div class=\" NB - trainer - section - body \ ">"
" <a href=\" http : // ios . newsblur . com / classify - author / % @ \ " "
2012-12-27 00:15:26 -08:00
" class=\" NB - story - author % @ \ ">%@</a>"
2012-12-25 19:03:50 -08:00
" </div>"
"</div>" ,
2012-12-24 23:01:25 -08:00
author ,
authorScore > 0 ? @ "NB-story-author-positive" : authorScore < 0 ? @ "NB-story-author-negative" : @ "" ,
2012-12-27 00:15:26 -08:00
[ self makeClassifier : author withType : @ "Author" score : authorScore ] ] ;
2012-12-24 23:01:25 -08:00
}
}
return storyAuthor ;
}
2012-12-27 00:15:26 -08:00
- ( NSString * ) makeFeedAuthors {
2014-04-18 15:50:32 -07:00
NSString * feedId = [ self feedId ] ;
2012-12-27 00:15:26 -08:00
NSString * feedAuthors = @ "" ;
2014-02-12 20:09:37 -08:00
NSArray * authorArray = appDelegate . storiesCollection . activePopularAuthors ;
2014-04-18 15:50:32 -07:00
NSMutableArray * userAuthorArray = [ NSMutableArray array ] ;
for ( NSString * trainedAuthor in [ [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
objectForKey : @ "authors" ] allKeys ] ) {
BOOL found = NO ;
for ( NSArray * classifierAuthor in authorArray ) {
if ( [ trainedAuthor isEqualToString : [ classifierAuthor objectAtIndex : 0 ] ] ) {
found = YES ;
break ;
}
}
if ( ! found ) {
[ userAuthorArray addObject : @ [ trainedAuthor , [ NSNumber numberWithInt : 0 ] ] ] ;
}
}
NSArray * authors = [ userAuthorArray arrayByAddingObjectsFromArray : authorArray ] ;
2014-03-03 16:21:26 -08:00
2014-04-18 15:50:32 -07:00
if ( [ authors count ] > 0 ) {
2012-12-27 00:15:26 -08:00
NSMutableArray * authorStrings = [ NSMutableArray array ] ;
2014-04-18 15:50:32 -07:00
for ( NSArray * authorObj in authors ) {
2012-12-27 00:15:26 -08:00
NSString * author = [ authorObj objectAtIndex : 0 ] ;
int authorCount = [ [ authorObj objectAtIndex : 1 ] intValue ] ;
2014-02-12 20:09:37 -08:00
int authorScore = [ [ [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
2012-12-27 00:15:26 -08:00
objectForKey : @ "authors" ]
objectForKey : author ] intValue ] ;
2014-04-18 15:50:32 -07:00
NSString * authorCountString = @ "" ;
if ( authorCount ) {
authorCountString = [ NSString stringWithFormat : @ "<span class=\" NB - classifier - count \ ">× %d</span>" ,
authorCount ] ;
}
2012-12-27 00:15:26 -08:00
NSString * authorHtml = [ NSString stringWithFormat : @ "<div class=\" NB - classifier - container \ ">"
" <a href=\" http : // ios . newsblur . com / classify - author / % @ \ " "
" class=\" NB - story - author % @ \ ">%@</a>"
2014-04-18 15:50:32 -07:00
" %@"
2012-12-27 00:15:26 -08:00
"</div>" ,
author ,
authorScore > 0 ? @ "NB-story-author-positive" : authorScore < 0 ? @ "NB-story-author-negative" : @ "" ,
[ self makeClassifier : author withType : @ "author" score : authorScore ] ,
2014-04-18 15:50:32 -07:00
authorCountString ] ;
2012-12-27 00:15:26 -08:00
[ authorStrings addObject : authorHtml ] ;
}
feedAuthors = [ NSString
stringWithFormat : @ "<div class=\" NB - trainer - section - inner \ ">"
" <div class=\" NB - trainer - section - title \ ">Authors</div>"
" <div class=\" NB - trainer - section - body \ ">"
" <div class=\" NB - story - authors \ ">"
" %@"
" </div>"
" </div>"
"</div>" ,
[ authorStrings componentsJoinedByString : @ "" ] ] ;
}
return feedAuthors ;
}
- ( NSString * ) makeStoryTags {
2014-03-03 16:21:26 -08:00
NSString * feedId = [ self feedId ] ;
2012-12-24 23:01:25 -08:00
NSString * storyTags = @ "" ;
2012-12-27 00:15:26 -08:00
2012-12-24 23:01:25 -08:00
if ( [ appDelegate . activeStory objectForKey : @ "story_tags" ] ) {
NSArray * tagArray = [ appDelegate . activeStory objectForKey : @ "story_tags" ] ;
if ( [ tagArray count ] > 0 ) {
NSMutableArray * tagStrings = [ NSMutableArray array ] ;
for ( NSString * tag in tagArray ) {
2014-02-12 20:09:37 -08:00
int tagScore = [ [ [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
2012-12-24 23:01:25 -08:00
objectForKey : @ "tags" ]
objectForKey : tag ] intValue ] ;
2012-12-27 00:15:26 -08:00
NSString * tagHtml = [ NSString stringWithFormat : @ "<div class=\" NB - classifier - container \ ">"
2012-12-25 19:03:50 -08:00
" <a href=\" http : // ios . newsblur . com / classify - tag / % @ \ " "
2012-12-27 00:15:26 -08:00
" class=\" NB - story - tag % @ \ ">%@</a>"
2012-12-25 19:03:50 -08:00
"</div>" ,
2012-12-24 23:01:25 -08:00
tag ,
tagScore > 0 ? @ "NB-story-tag-positive" : tagScore < 0 ? @ "NB-story-tag-negative" : @ "" ,
2012-12-27 00:15:26 -08:00
[ self makeClassifier : tag withType : @ "Tag" score : tagScore ] ] ;
2012-12-24 23:01:25 -08:00
[ tagStrings addObject : tagHtml ] ;
}
storyTags = [ NSString
2012-12-25 19:03:50 -08:00
stringWithFormat : @ "<div class=\" NB - trainer - section - inner \ ">"
" <div class=\" NB - trainer - section - title \ ">Story Tags</div>"
" <div class=\" NB - trainer - section - body \ ">"
2012-12-27 00:15:26 -08:00
" <div class=\" NB - story - tags \ ">"
2012-12-25 19:03:50 -08:00
" %@"
" </div>"
" </div>"
2012-12-24 23:01:25 -08:00
"</div>" ,
[ tagStrings componentsJoinedByString : @ "" ] ] ;
}
}
return storyTags ;
}
2012-12-27 00:15:26 -08:00
- ( NSString * ) makeFeedTags {
2014-03-03 16:21:26 -08:00
NSString * feedId = [ self feedId ] ;
2012-12-27 00:15:26 -08:00
NSString * feedTags = @ "" ;
2014-02-12 20:09:37 -08:00
NSArray * tagArray = appDelegate . storiesCollection . activePopularTags ;
2014-04-18 15:50:32 -07:00
NSMutableArray * userTagArray = [ NSMutableArray array ] ;
for ( NSString * trainedTag in [ [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
objectForKey : @ "tags" ] allKeys ] ) {
BOOL found = NO ;
for ( NSArray * classifierTag in tagArray ) {
if ( [ trainedTag isEqualToString : [ classifierTag objectAtIndex : 0 ] ] ) {
found = YES ;
break ;
}
}
if ( ! found ) {
[ userTagArray addObject : @ [ trainedTag , [ NSNumber numberWithInt : 0 ] ] ] ;
}
}
NSArray * tags = [ userTagArray arrayByAddingObjectsFromArray : tagArray ] ;
if ( [ tags count ] > 0 ) {
2012-12-27 00:15:26 -08:00
NSMutableArray * tagStrings = [ NSMutableArray array ] ;
2014-04-18 15:50:32 -07:00
for ( NSArray * tagObj in tags ) {
2012-12-27 00:15:26 -08:00
NSString * tag = [ tagObj objectAtIndex : 0 ] ;
int tagCount = [ [ tagObj objectAtIndex : 1 ] intValue ] ;
2014-02-12 20:09:37 -08:00
int tagScore = [ [ [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
2012-12-27 00:15:26 -08:00
objectForKey : @ "tags" ]
objectForKey : tag ] intValue ] ;
2014-04-18 15:50:32 -07:00
NSString * tagCountString = @ "" ;
if ( tagCount ) {
tagCountString = [ NSString stringWithFormat : @ "<span class=\" NB - classifier - count \ ">× %d</span>" ,
tagCount ] ;
}
2012-12-27 00:15:26 -08:00
NSString * tagHtml = [ NSString stringWithFormat : @ "<div class=\" NB - classifier - container \ ">"
" <a href=\" http : // ios . newsblur . com / classify - tag / % @ \ " "
" class=\" NB - story - tag % @ \ ">%@</a>"
2014-04-18 15:50:32 -07:00
" %@"
2012-12-27 00:15:26 -08:00
"</div>" ,
tag ,
tagScore > 0 ? @ "NB-story-tag-positive" : tagScore < 0 ? @ "NB-story-tag-negative" : @ "" ,
[ self makeClassifier : tag withType : @ "Tag" score : tagScore ] ,
2014-04-18 15:50:32 -07:00
tagCountString ] ;
2012-12-27 00:15:26 -08:00
[ tagStrings addObject : tagHtml ] ;
}
feedTags = [ NSString
stringWithFormat : @ "<div class=\" NB - trainer - section - inner \ ">"
" <div class=\" NB - trainer - section - title \ ">Story Tags</div>"
" <div class=\" NB - trainer - section - body \ ">"
" <div class=\" NB - story - tags \ ">"
" %@"
" </div>"
" </div>"
"</div>" ,
[ tagStrings componentsJoinedByString : @ "" ] ] ;
}
return feedTags ;
}
2012-12-24 23:01:25 -08:00
- ( NSString * ) makePublisher {
2012-12-27 00:15:26 -08:00
NSString * feedId ;
NSString * feedTitle ;
if ( self . feedTrainer ) {
2014-02-12 20:09:37 -08:00
feedId = [ NSString stringWithFormat : @ "%@" , [ appDelegate . storiesCollection . activeFeed objectForKey : @ "id" ] ] ;
feedTitle = [ appDelegate . storiesCollection . activeFeed objectForKey : @ "feed_title" ] ;
2012-12-27 00:15:26 -08:00
} else {
feedId = [ NSString stringWithFormat : @ "%@" , [ appDelegate . activeStory
objectForKey : @ "story_feed_id" ] ] ;
2012-12-28 11:34:06 -08:00
NSDictionary * feed = [ appDelegate getFeed : feedId ] ;
feedTitle = [ feed objectForKey : @ "feed_title" ] ;
2012-12-27 00:15:26 -08:00
}
2014-02-12 20:09:37 -08:00
int publisherScore = [ [ [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
2012-12-27 00:15:26 -08:00
objectForKey : @ "feeds" ] objectForKey : feedId ] intValue ] ;
2012-12-25 19:03:50 -08:00
2014-02-24 18:56:51 -08:00
UIImage * favicon = [ appDelegate getFavicon : feedId ] ;
2013-02-07 11:46:44 -08:00
NSData * faviconData = UIImagePNGRepresentation ( favicon ) ;
NSString * feedImageUrl = [ NSString stringWithFormat : @ "data:image/png;charset=utf-8;base64,%@" ,
2017-11-30 16:57:10 -08:00
[ faviconData base64EncodedDataWithOptions : NSDataBase64Encoding64CharacterLineLength ] ] ;
2013-02-07 11:46:44 -08:00
NSString * publisherTitle = [ NSString stringWithFormat : @ "<img class=\" feed_favicon \ " src=\" % @ \ "> %@" ,
feedImageUrl , feedTitle ] ;
2012-12-25 19:03:50 -08:00
NSString * storyPublisher = [ NSString stringWithFormat : @ "<div class=\" NB - trainer - section - inner \ ">"
" <div class=\" NB - trainer - section - title \ ">Publisher</div>"
" <div class=\" NB - trainer - section - body \ ">"
2012-12-27 00:15:26 -08:00
" <div class=\" NB - classifier - container \ ">"
2012-12-27 18:37:05 -08:00
" <a href=\" http : // ios . newsblur . com / classify - feed / % @ \ " "
" class=\" NB - story - publisher NB - story - publisher - % @ \ ">%@</a>"
2012-12-27 00:15:26 -08:00
" </div>"
2012-12-25 19:03:50 -08:00
" </div>"
"</div" ,
2012-12-27 00:15:26 -08:00
feedId ,
2012-12-27 18:37:05 -08:00
publisherScore > 0 ? @ "positive" : publisherScore < 0 ? @ "negative" : @ "" ,
2013-02-07 11:46:44 -08:00
[ self makeClassifier : publisherTitle
withType : @ "publisher"
score : publisherScore ] ] ;
2012-12-25 19:03:50 -08:00
2012-12-24 23:01:25 -08:00
return storyPublisher ;
}
- ( NSString * ) makeTitle {
NSString * feedId = [ NSString stringWithFormat : @ "%@" , [ appDelegate . activeStory
objectForKey : @ "story_feed_id" ] ] ;
NSString * storyTitle = [ appDelegate . activeStory objectForKey : @ "story_title" ] ;
2012-12-27 18:37:05 -08:00
2012-12-25 19:03:50 -08:00
if ( ! storyTitle ) {
return @ "" ;
}
2014-02-12 20:09:37 -08:00
NSMutableDictionary * classifiers = [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
2012-12-24 23:01:25 -08:00
objectForKey : @ "titles" ] ;
2012-12-27 18:37:05 -08:00
NSMutableArray * titleStrings = [ NSMutableArray array ] ;
for ( NSString * title in classifiers ) {
if ( [ storyTitle containsString : title ] ) {
int titleScore = [ [ classifiers objectForKey : title ] intValue ] ;
NSString * titleClassifier = [ NSString stringWithFormat : @
"<div class=\" NB - classifier - container \ ">"
" <a href=\" http : // ios . newsblur . com / classify - title / % @ \ " "
" class=\" NB - story - title NB - story - title - % @ \ ">%@</a>"
"</div>" ,
title ,
titleScore > 0 ? @ "positive" : titleScore < 0 ? @ "negative" : @ "" ,
[ self makeClassifier : title withType : @ "title" score : titleScore ] ] ;
[ titleStrings addObject : titleClassifier ] ;
2012-12-24 23:01:25 -08:00
}
}
2012-12-27 18:37:05 -08:00
NSString * titleClassifiers ;
if ( [ titleStrings count ] ) {
titleClassifiers = [ titleStrings componentsJoinedByString : @ "" ] ;
} else {
titleClassifiers = @ "<div class=\" NB - title - info \ ">Tap and hold the title</div>" ;
}
2012-12-25 19:03:50 -08:00
NSString * titleTrainer = [ NSString stringWithFormat : @ "<div class=\" NB - trainer - section - inner \ ">"
" <div class=\" NB - trainer - section - title \ ">Story Title</div>"
" <div class=\" NB - trainer - section - body NB - title \ ">"
2013-01-07 16:34:59 -08:00
" <div class=\" NB - title - trainer \ ">"
" <span>%@</span>"
" </div>"
2012-12-27 18:37:05 -08:00
" %@"
2012-12-25 19:03:50 -08:00
" </div>"
2012-12-27 18:37:05 -08:00
"</div>" , storyTitle , titleClassifiers ] ;
2012-12-25 19:03:50 -08:00
return titleTrainer ;
}
2015-09-21 13:59:31 -07:00
- ( NSString * ) makeFeedTitles {
NSString * feedId = [ self feedId ] ;
NSMutableDictionary * classifiers = [ [ appDelegate . storiesCollection . activeClassifiers objectForKey : feedId ]
objectForKey : @ "titles" ] ;
NSMutableArray * titleStrings = [ NSMutableArray array ] ;
for ( NSString * title in classifiers ) {
int titleScore = [ [ classifiers objectForKey : title ] intValue ] ;
NSString * titleClassifier = [ NSString stringWithFormat : @
"<div class=\" NB - classifier - container \ ">"
" <a href=\" http : // ios . newsblur . com / classify - title / % @ \ " "
" class=\" NB - story - title NB - story - title - % @ \ ">%@</a>"
"</div>" ,
title ,
titleScore > 0 ? @ "positive" : titleScore < 0 ? @ "negative" : @ "" ,
[ self makeClassifier : title withType : @ "title" score : titleScore ] ] ;
[ titleStrings addObject : titleClassifier ] ;
}
NSString * titleClassifiers = [ titleStrings componentsJoinedByString : @ "" ] ;
NSString * titleTrainer = [ NSString stringWithFormat : @ "<div class=\" NB - trainer - section - inner \ ">"
" <div class=\" NB - trainer - section - title \ ">Story Titles</div>"
" <div class=\" NB - trainer - section - body \ ">"
" <div class=\" NB - story - titles \ ">"
" %@"
" </div>"
" </div>"
"</div>" , titleClassifiers ] ;
return titleTrainer ;
}
2012-12-27 00:15:26 -08:00
- ( NSString * ) makeClassifier : ( NSString * ) classifierName withType : ( NSString * ) classifierType score : ( int ) score {
NSString * classifier = [ NSString stringWithFormat : @ "<span class=\" NB - classifier NB - classifier - % @ NB - classifier - % @ \ ">"
2012-12-25 19:03:50 -08:00
"<div class=\" NB - classifier - icon - like \ "></div>"
"<div class=\" NB - classifier - icon - dislike \ ">"
" <div class=\" NB - classifier - icon - dislike - inner \ "></div>"
"</div>"
"<label><b>%@: </b><span>%@</span></label>"
"</span>" ,
classifierType ,
2012-12-27 00:15:26 -08:00
score > 0 ? @ "like" : score < 0 ? @ "dislike" : @ "" ,
2012-12-25 19:03:50 -08:00
classifierType ,
classifierName ] ;
return classifier ;
2012-12-24 23:01:25 -08:00
}
# pragma mark -
# pragma mark Actions
- ( IBAction ) doCloseDialog : ( id ) sender {
2015-12-15 12:37:18 -08:00
[ appDelegate hidePopover ] ;
2013-06-17 11:50:13 -07:00
[ appDelegate . trainerViewController dismissViewControllerAnimated : YES completion : nil ] ;
2012-12-24 23:01:25 -08:00
}
2012-12-27 18:37:05 -08:00
- ( void ) changeTitle : ( id ) sender score : ( int ) score {
NSString * feedId = [ NSString stringWithFormat : @ "%@" , [ appDelegate . activeStory
objectForKey : @ "story_feed_id" ] ] ;
2020-02-23 15:21:32 -08:00
[ self . webView evaluateJavaScript : @ "window.getSelection().toString()" completionHandler : ^ ( id result , NSError * error ) {
[ self . appDelegate toggleTitleClassifier : result feedId : feedId score : score ] ;
} ] ;
2012-12-25 19:03:50 -08:00
}
2020-02-23 15:21:32 -08:00
- ( void ) webView : ( WKWebView * ) webView decidePolicyForNavigationAction : ( WKNavigationAction * ) navigationAction decisionHandler : ( void ( ^ ) ( WKNavigationActionPolicy ) ) decisionHandler {
NSURLRequest * request = navigationAction . request ;
2012-12-27 18:37:05 -08:00
NSURL * url = [ request URL ] ;
NSArray * urlComponents = [ url pathComponents ] ;
NSString * action = @ "" ;
2014-04-18 15:50:47 -07:00
NSString * feedId = [ self feedId ] ;
2012-12-28 11:34:06 -08:00
2012-12-27 18:37:05 -08:00
if ( [ urlComponents count ] > 1 ) {
action = [ NSString stringWithFormat : @ "%@" , [ urlComponents objectAtIndex : 1 ] ] ;
}
NSLog ( @ "Tapped url: %@" , url ) ;
if ( [ [ url host ] isEqualToString : @ "ios.newsblur.com" ] ) {
if ( [ action isEqualToString : @ "classify-author" ] ) {
NSString * author = [ NSString stringWithFormat : @ "%@" , [ urlComponents objectAtIndex : 2 ] ] ;
[ self . appDelegate toggleAuthorClassifier : author feedId : feedId ] ;
} else if ( [ action isEqualToString : @ "classify-tag" ] ) {
NSString * tag = [ NSString stringWithFormat : @ "%@" , [ urlComponents objectAtIndex : 2 ] ] ;
[ self . appDelegate toggleTagClassifier : tag feedId : feedId ] ;
} else if ( [ action isEqualToString : @ "classify-title" ] ) {
NSString * title = [ NSString stringWithFormat : @ "%@" , [ urlComponents objectAtIndex : 2 ] ] ;
[ self . appDelegate toggleTitleClassifier : title feedId : feedId score : 0 ] ;
} else if ( [ action isEqualToString : @ "classify-feed" ] ) {
NSString * feedId = [ NSString stringWithFormat : @ "%@" , [ urlComponents objectAtIndex : 2 ] ] ;
[ self . appDelegate toggleFeedClassifier : feedId ] ;
}
2020-02-23 15:21:32 -08:00
decisionHandler ( WKNavigationActionPolicyCancel ) ;
return ;
2012-12-27 18:37:05 -08:00
}
2020-02-23 15:21:32 -08:00
decisionHandler ( WKNavigationActionPolicyAllow ) ;
2012-12-25 19:03:50 -08:00
}
@ end
@ implementation TrainerWebView
- ( BOOL ) canPerformAction : ( SEL ) action withSender : ( id ) sender {
2012-12-27 18:37:05 -08:00
if ( action = = @ selector ( focusTitle : ) || action = = @ selector ( hideTitle : ) ) {
2012-12-25 19:03:50 -08:00
return YES ;
} else {
return NO ;
}
}
2012-12-27 18:37:05 -08:00
- ( void ) focusTitle : ( id ) sender {
NewsBlurAppDelegate * appDelegate = [ NewsBlurAppDelegate sharedAppDelegate ] ;
[ appDelegate . trainerViewController changeTitle : sender score : 1 ] ;
}
- ( void ) hideTitle : ( id ) sender {
2012-12-25 19:03:50 -08:00
NewsBlurAppDelegate * appDelegate = [ NewsBlurAppDelegate sharedAppDelegate ] ;
2012-12-27 18:37:05 -08:00
[ appDelegate . trainerViewController changeTitle : sender score : -1 ] ;
2012-12-25 19:03:50 -08:00
}
2016-01-24 12:01:12 -05:00
// Work around iOS 9 issue where menu doesn ' t appear the first time
// http : // stackoverflow . com / questions / 32685198 /
- ( BOOL ) canBecomeFirstResponder {
return YES ;
}
2012-12-24 23:01:25 -08:00
@ end