mirror of
https://github.com/leanote/leanote-ios.git
synced 2025-10-17 00:24:09 +00:00
924 lines
30 KiB
Objective-C
924 lines
30 KiB
Objective-C
//
|
|
// NoteViewController.m
|
|
// Leanote
|
|
//
|
|
// Created by life on 15/5/31.
|
|
// Copyright (c) 2015 Leanote.com. All rights reserved.
|
|
//
|
|
|
|
#import "NoteViewController.h"
|
|
#import "BaseViewController.h"
|
|
|
|
@import AssetsLibrary;
|
|
@import AVFoundation;
|
|
#import <CocoaLumberjack/CocoaLumberjack.h>
|
|
|
|
#import "SVProgressHUD.h"
|
|
|
|
#import "WPEditorField.h"
|
|
#import "WPEditorView.h"
|
|
|
|
#import "LeaAlert.h"
|
|
|
|
#import "LeaButtonForNavigationBar.h"
|
|
#import <WordPress-iOS-Shared/UIImage+Util.h>
|
|
#import <WordPress-iOS-Shared/WPFontManager.h>
|
|
#import <WordPress-iOS-Shared/WPStyleGuide.h>
|
|
#import <WPMediaPicker/WPMediaPicker.h>
|
|
|
|
#import "NoteSettingsTableViewController.h"
|
|
#import "LeaWebViewController.h"
|
|
|
|
//#import "NoteService.h"
|
|
//#import "NotebookService.h"
|
|
#import "FileService.h"
|
|
#import "Leas.h"
|
|
|
|
#import "UserService.h"
|
|
|
|
#import "Common.h"
|
|
#import "ApiMsg.h"
|
|
|
|
#import "LeaImageViewController.h"
|
|
#import "LeaImagePagerViewController.h"
|
|
#import "LeaImageSliderViewController.h"
|
|
|
|
typedef NS_ENUM(NSUInteger, WPViewControllerActionSheet) {
|
|
WPViewControllerActionSheetImageUploadStop = 200,
|
|
WPViewControllerActionSheetImageUploadRetry = 201,
|
|
WPViewControllerActionSheetVideoUploadStop = 202,
|
|
WPViewControllerActionSheetVideoUploadRetry = 203
|
|
};
|
|
|
|
// 按钮大小, 间距
|
|
const CGRect NavigationBarButtonRect = {
|
|
.origin.x = 0.0f,
|
|
.origin.y = 0.0f,
|
|
.size.width = 30.0f,
|
|
.size.height = 30.0f
|
|
};
|
|
static CGFloat const SpacingBetweeenNavbarButtons = 20.0f;
|
|
//static CGFloat const RightSpacingOnExitNavbarButton = 5.0f;
|
|
static NSDictionary *DisabledButtonBarStyle;
|
|
static NSDictionary *EnabledButtonBarStyle;
|
|
static NSInteger const MaximumNumberOfPictures = 10;
|
|
|
|
|
|
@interface NoteViewController () <CTAssetsPickerControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIActionSheetDelegate, WPMediaPickerViewControllerDelegate>
|
|
|
|
@property(nonatomic, strong) NSMutableDictionary *mediaAdded;
|
|
@property(nonatomic, strong) NSString *selectedMediaID;
|
|
@property(nonatomic, strong) NSCache *videoPressCache;
|
|
|
|
@property (strong, nonatomic) UIPopoverController *masterPopoverController;
|
|
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
|
|
@property (weak, nonatomic) IBOutlet UITextView *textView; // 为什么要有?
|
|
|
|
// 按钮
|
|
@property (nonatomic, strong) UIBarButtonItem *cancelButton; // 取消, 即返回
|
|
@property (nonatomic, strong) UIBarButtonItem *editBarButtonItem; // 编辑按钮
|
|
@property (nonatomic, strong) UIBarButtonItem *saveBarButtonItem; // 保存按钮
|
|
@property (nonatomic, strong) UIBarButtonItem *previewBarButtonItem; // 预览按钮
|
|
@property (nonatomic, strong) UIBarButtonItem *optionsBarButtonItem; // 配置按钮
|
|
|
|
@property (nonatomic, strong) UIActionSheet* actionSheet;
|
|
|
|
@property (nonatomic) BOOL isMarkdown;
|
|
|
|
@property (nonatomic) BOOL edited;
|
|
|
|
@property BOOL isInited;
|
|
|
|
@end;
|
|
|
|
@implementation NoteViewController
|
|
|
|
@synthesize textView = _textView; // 为什么要有?
|
|
@synthesize note = _note;
|
|
|
|
|
|
// 将要结束编辑, 保存笔记
|
|
// force, 强制保存, 不管title, content有没有变化
|
|
- (BOOL)saveNote:(BOOL)force
|
|
{
|
|
NSString *title = [Common trimNewLine:[self titleText]];
|
|
NSString *content = [self bodyText];
|
|
|
|
// 更新笔记
|
|
if(self.note != nil) {
|
|
if(self.edited) {
|
|
BOOL contentIsDirty = ![self.note.content isEqualToString:content];
|
|
BOOL titleIsDirty = ![self.note.title isEqualToString:title];
|
|
if(contentIsDirty || titleIsDirty)
|
|
{
|
|
[Leas.note updateNote:self.note title:title content:content];
|
|
}
|
|
else {
|
|
NSLog(@" not need UPDATE");
|
|
return NO;
|
|
}
|
|
}
|
|
else {
|
|
NSLog(@" not need UPDATE readonly");
|
|
return NO;
|
|
}
|
|
|
|
// 新建一个笔记
|
|
} else {
|
|
if(force || (![Common isBlankString:title] || ![Common isBlankString:content])) {
|
|
NSLog(@"add note");
|
|
|
|
self.note = [Leas.note addNote:title content:content
|
|
notebook:self.notebook tag:self.tag];
|
|
}
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
|
|
#pragma mark - Setter
|
|
|
|
// Master View调用
|
|
- (void)setNote:(Note *)note
|
|
{
|
|
if (_note != note)
|
|
{
|
|
_note = note;
|
|
// Update the view.
|
|
// [self configureView];
|
|
}
|
|
}
|
|
|
|
- (void)viewDidLoad
|
|
{
|
|
self.isMarkdown = NO;
|
|
if(self.note) {
|
|
self.isMarkdown = [self.note.isMarkdown boolValue];
|
|
}
|
|
// 表示是新增, hide status bar
|
|
else {
|
|
self.isMarkdown = ![UserService isNormalEditor];
|
|
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
|
|
// kWPEditorViewControllerModeEdit
|
|
}
|
|
[super initWithMode:kWPEditorViewControllerModePreview isMarkdown:self.isMarkdown];
|
|
|
|
[super viewDidLoad];
|
|
|
|
self.delegate = self;
|
|
|
|
[self restoreBarStyle];
|
|
|
|
// 按钮初始化
|
|
[self initNavigationBarRightButtons];
|
|
}
|
|
|
|
// 这里, 有大问题, 如果是新建的
|
|
// 图片pick消失后还是会执行这个, 会startEditing, 会focus title
|
|
- (void)viewDidAppear:(BOOL)animated
|
|
{
|
|
// 必须要, 不然插入图片会找不到selection问题
|
|
[super viewDidAppear:animated];
|
|
|
|
// 当都显示完后, 才开始编辑, 显示键盘
|
|
if(!self.note && !self.isInited) {
|
|
[self startEditing];
|
|
[self enableRightButtons];
|
|
}
|
|
|
|
// 确保只执行一次
|
|
// 放这里, 为了速度快
|
|
if(!self.isInited) {
|
|
self.mediaAdded = [NSMutableDictionary dictionary];
|
|
self.videoPressCache = [[NSCache alloc] init];
|
|
|
|
// 样式缓存
|
|
DisabledButtonBarStyle = @{NSFontAttributeName: [WPStyleGuide regularTextFontSemiBold], NSForegroundColorAttributeName: [UIColor colorWithWhite:1.0 alpha:0.25]};
|
|
EnabledButtonBarStyle = @{NSFontAttributeName: [WPStyleGuide regularTextFontSemiBold], NSForegroundColorAttributeName: [UIColor whiteColor]};
|
|
}
|
|
|
|
self.isInited = YES;
|
|
}
|
|
|
|
// 消失后再save, 笔记内容会消失吗?
|
|
-(void) viewWillDisappear:(BOOL)animated {
|
|
// 是从本view消息的
|
|
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
|
|
// back button was pressed. We know this is true because self is no longer
|
|
// in the navigation stack.
|
|
|
|
NSLog(@"pop");
|
|
|
|
[self saveNote:NO];
|
|
|
|
[Leas.note pushNoteAndWrite:self.note success:^{
|
|
// tips 提示同步成功
|
|
[self showSuccessMsg:NSLocalizedString(@"Synchronize note successful", @"")];
|
|
} fail:^(id ret) {
|
|
[self showErrorMsg:NSLocalizedString(@"Synchronize note failed", @"") ret:ret];
|
|
}];
|
|
}
|
|
|
|
// 一直在loading 内容
|
|
[self hideProgress];
|
|
|
|
[super viewWillDisappear:animated];
|
|
}
|
|
|
|
// 当笔记内容load后才enable
|
|
- (void) enableRightButtons
|
|
{
|
|
self.saveBarButtonItem.enabled = YES;
|
|
self.optionsBarButtonItem.enabled = YES;
|
|
}
|
|
|
|
- (void)initNavigationBarRightButtons
|
|
{
|
|
NSArray* rightBarButtons = @[
|
|
[self saveBarButtonItem],
|
|
[self optionsBarButtonItem],
|
|
];
|
|
// 初始时disable
|
|
self.saveBarButtonItem.enabled = NO;
|
|
self.optionsBarButtonItem.enabled = NO;
|
|
|
|
[self.navigationItem setRightBarButtonItems:rightBarButtons animated:YES];
|
|
}
|
|
|
|
# pragma mark - Custom UI elements
|
|
|
|
// 保存之后 -> 只读状态
|
|
- (void)refreshNavigationBarRightButtons:(BOOL)editingChanged
|
|
{
|
|
if ([self isEditing]) {
|
|
self.edited = YES;
|
|
self.saveBarButtonItem.title = NSLocalizedString(@"Save", @"");
|
|
} else {
|
|
self.saveBarButtonItem.title = NSLocalizedString(@"Edit", @"");
|
|
if (!self.saveBarButtonItem.enabled) {
|
|
self.saveBarButtonItem.enabled = YES;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 生成按钮通用方法
|
|
- (LeaButtonForNavigationBar*)buttonForBarWithImageNamed:(NSString*)imageName
|
|
frame:(CGRect)frame
|
|
target:(id)target
|
|
selector:(SEL)selector
|
|
{
|
|
NSAssert([imageName isKindOfClass:[NSString class]],
|
|
@"Expected imageName to be a non nil string.");
|
|
|
|
UIImage* image = [UIImage imageNamed:imageName];
|
|
|
|
LeaButtonForNavigationBar* button = [[LeaButtonForNavigationBar alloc] initWithFrame:frame];
|
|
|
|
[button setImage:image forState:UIControlStateNormal];
|
|
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
return button;
|
|
}
|
|
|
|
// 配置按钮
|
|
- (UIBarButtonItem *)optionsBarButtonItem
|
|
{
|
|
if (!_optionsBarButtonItem) {
|
|
LeaButtonForNavigationBar *button = [self buttonForBarWithImageNamed:@"icon-posts-editor-options"
|
|
frame:NavigationBarButtonRect
|
|
target:self
|
|
selector:@selector(showSettings)];
|
|
|
|
button.removeDefaultRightSpacing = YES;
|
|
button.rightSpacing = SpacingBetweeenNavbarButtons / 2.0f;
|
|
button.removeDefaultLeftSpacing = YES;
|
|
button.leftSpacing = SpacingBetweeenNavbarButtons / 2.0f;
|
|
NSString *optionsTitle = NSLocalizedString(@"Options", @"Title of the Post Settings navigation button in the Post Editor. Tapping shows settings and options related to the post being edited.");
|
|
button.accessibilityLabel = optionsTitle;
|
|
button.accessibilityIdentifier = @"Options";
|
|
_optionsBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
|
|
}
|
|
|
|
return _optionsBarButtonItem;
|
|
}
|
|
|
|
// 编辑/完成按钮
|
|
- (UIBarButtonItem *)saveBarButtonItem
|
|
{
|
|
if (!_saveBarButtonItem) {
|
|
NSString *buttonTitle = NSLocalizedString(@"Edit", @"");
|
|
|
|
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:buttonTitle
|
|
style:[WPStyleGuide barButtonStyleForDone]
|
|
target:self
|
|
action:@selector(editTouchedUpInside)];
|
|
|
|
// Seems to be an issue witht the appearance proxy not being respected, so resetting these here
|
|
[saveButton setTitleTextAttributes:EnabledButtonBarStyle forState:UIControlStateNormal];
|
|
[saveButton setTitleTextAttributes:DisabledButtonBarStyle forState:UIControlStateDisabled];
|
|
_saveBarButtonItem = saveButton;
|
|
}
|
|
|
|
return _saveBarButtonItem;
|
|
}
|
|
|
|
#pragma mark - Navigation Bar
|
|
|
|
// 不加 不能隐藏状态栏
|
|
BOOL hiddenBar = NO;
|
|
//- (BOOL)prefersStatusBarHidden
|
|
//{
|
|
// return hiddenBar;
|
|
//}
|
|
|
|
- (void)editTouchedUpInside
|
|
{
|
|
// isEditting, stopEditing是继承过来的
|
|
if (self.isEditing) {
|
|
[self stopEditing];
|
|
hiddenBar = NO;
|
|
} else {
|
|
[self startEditing];
|
|
hiddenBar = YES;
|
|
}
|
|
|
|
// [self prefersStatusBarHidden];
|
|
// [self setNeedsStatusBarAppearanceUpdate];
|
|
|
|
[[UIApplication sharedApplication] setStatusBarHidden:hiddenBar withAnimation:UIStatusBarAnimationSlide];
|
|
|
|
[self refreshNavigationBarRightButtons:YES];
|
|
}
|
|
|
|
// 显示配置
|
|
- (void)showSettings
|
|
{
|
|
[self saveNote:YES];
|
|
NoteSettingsTableViewController *vc = [[[NoteSettingsTableViewController class] alloc] initWithNote:self.note shouldHideStatusBar:YES];
|
|
|
|
vc.hidesBottomBarWhenPushed = YES;
|
|
|
|
[self.editorView saveSelection];
|
|
|
|
[self.navigationController pushViewController:vc animated:YES];
|
|
}
|
|
|
|
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
|
[self.editorView saveSelection];
|
|
[super prepareForSegue:segue sender:sender];
|
|
}
|
|
|
|
#pragma mark - IBActions
|
|
|
|
- (IBAction)exit:(UIStoryboardSegue*)segue
|
|
{
|
|
}
|
|
|
|
// 编辑方法
|
|
#pragma mark - WPEditorViewControllerDelegate
|
|
|
|
- (void)editorDidBeginEditing:(WPEditorViewController *)editorController
|
|
{
|
|
// DDLogInfo(@"Editor did begin editing.");
|
|
[self refreshNavigationBarRightButtons:YES];
|
|
}
|
|
|
|
- (void)editorDidEndEditing:(WPEditorViewController *)editorController
|
|
{
|
|
// DDLogInfo(@"Editor did end editing.");
|
|
// DDLogInfo(self.bodyText);
|
|
[self saveNote:NO];
|
|
}
|
|
|
|
// 编辑器加载后设置内容
|
|
- (void)editorDidFinishLoadingDOM:(WPEditorViewController *)editorController
|
|
{
|
|
// NSString *path = [[NSBundle mainBundle] pathForResource:@"content" ofType:@"html"];
|
|
// NSString *htmlParam = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
|
|
// self.titleText = self.note.title;
|
|
// self.bodyText = self.note.content;
|
|
|
|
if(self.note) {
|
|
[self setTitleText:self.note.title];
|
|
|
|
[self showProgress];
|
|
|
|
[Leas.note getNoteContent:self.note success:^(NSString * content) {
|
|
[self setBodyText:content];
|
|
[self enableRightButtons];
|
|
[self hideProgress];
|
|
} fail:^{
|
|
[self hideProgress];
|
|
[LeaAlert showAlertWithTitle:NSLocalizedString(@"Error", nil) message:NSLocalizedString(@"Cannot fetch note's content", nil) withSupportButton:NO okPressedBlock:^(UIAlertView *alertView) {
|
|
// 返回
|
|
[self.navigationController popViewControllerAnimated:YES];
|
|
}];
|
|
}];
|
|
}
|
|
}
|
|
|
|
- (BOOL)editorShouldDisplaySourceView:(WPEditorViewController *)editorController
|
|
{
|
|
[self.editorView pauseAllVideos];
|
|
return YES;
|
|
}
|
|
|
|
- (void)editorDidPressMedia:(WPEditorViewController *)editorController
|
|
{
|
|
// DDLogInfo(@"Pressed Media!");
|
|
[self showPhotoPicker];
|
|
}
|
|
|
|
- (void)editorTitleDidChange:(WPEditorViewController *)editorController
|
|
{
|
|
// DDLogInfo(@"Editor title did change: %@", self.titleText);
|
|
}
|
|
|
|
- (void)editorTextDidChange:(WPEditorViewController *)editorController
|
|
{
|
|
// DDLogInfo(@"Editor body text changed: %@", self.bodyText);
|
|
}
|
|
|
|
- (void)editorViewController:(WPEditorViewController *)editorViewController fieldCreated:(WPEditorField*)field
|
|
{
|
|
// DDLogInfo(@"Editor field created: %@", field.nodeId);
|
|
}
|
|
|
|
// 点击图片时的操作
|
|
// 怎么让图片不可点?
|
|
- (void)editorViewController:(WPEditorViewController*)editorViewController
|
|
imageTapped:(NSString *)imageId
|
|
url:(NSURL *)url
|
|
imageMeta:(WPImageMeta *)imageMeta
|
|
{
|
|
// 1表示是editable的, 0表示不可editable
|
|
if ([imageId isEqualToString:@"1"]) {
|
|
// [self showImageDetailsForImageMeta:imageMeta];
|
|
} else {
|
|
[self showActionTapImage:[url absoluteString]];
|
|
}
|
|
}
|
|
|
|
// 非编辑模式下点击链接
|
|
- (void)editorViewController:(WPEditorViewController*)editorViewController
|
|
linkTapped:(NSString *)url
|
|
{
|
|
LeaWebViewController *webViewController = [[LeaWebViewController alloc] init];
|
|
webViewController.url = [NSURL URLWithString:url];
|
|
// [self.navigationController pushViewController:webViewController animated:YES];
|
|
|
|
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:webViewController];
|
|
[self.navigationController presentViewController:navController animated:YES completion:nil];
|
|
}
|
|
|
|
- (void)editorViewController:(WPEditorViewController*)editorViewController
|
|
videoTapped:(NSString *)videoId
|
|
url:(NSURL *)url
|
|
{
|
|
[self showPromptForVideoWithID:videoId];
|
|
}
|
|
|
|
- (void)editorViewController:(WPEditorViewController *)editorViewController imageReplaced:(NSString *)imageId
|
|
{
|
|
[self.mediaAdded removeObjectForKey:imageId];
|
|
}
|
|
|
|
- (void)editorViewController:(WPEditorViewController *)editorViewController videoReplaced:(NSString *)videoId
|
|
{
|
|
[self.mediaAdded removeObjectForKey:videoId];
|
|
}
|
|
|
|
- (void)editorViewController:(WPEditorViewController *)editorViewController videoPressInfoRequest:(NSString *)videoID
|
|
{
|
|
NSDictionary * videoPressInfo = [self.videoPressCache objectForKey:videoID];
|
|
NSString * videoURL = videoPressInfo[@"source"];
|
|
NSString * posterURL = videoPressInfo[@"poster"];
|
|
if (videoURL) {
|
|
[self.editorView setVideoPress:videoID source:videoURL poster:posterURL];
|
|
}
|
|
}
|
|
|
|
- (void)editorViewController:(WPEditorViewController *)editorViewController mediaRemoved:(NSString *)mediaID
|
|
{
|
|
NSProgress * progress = self.mediaAdded[mediaID];
|
|
[progress cancel];
|
|
}
|
|
|
|
#pragma mark - Media actions
|
|
|
|
// 查看图片的详细信息
|
|
/*
|
|
- (void)showImageDetailsForImageMeta:(WPImageMeta *)imageMeta
|
|
{
|
|
return;
|
|
|
|
WPImageMetaViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"WPImageMetaViewController"];
|
|
controller.imageMeta = imageMeta;
|
|
controller.delegate = self;
|
|
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
|
|
[self.navigationController presentViewController:navController animated:YES completion:nil];
|
|
}
|
|
*/
|
|
|
|
// TODO 有个action保存到本地图片中
|
|
- (void)showActionTapImage:(NSString *)url
|
|
{
|
|
NSArray *urlArr = [url componentsSeparatedByString:@","]; // 以','分隔, 最后一个是当前url
|
|
NSString *curUrlStr = [urlArr lastObject];
|
|
NSMutableArray *realUrls = [[NSMutableArray alloc] init];
|
|
|
|
// fix url, 整理出可以显示的图片
|
|
for(int i = 0; i < [urlArr count] - 1; ++i) {
|
|
NSString *each = urlArr[i];
|
|
|
|
NSString *fileId = [Common getFileIdFromUrl:each];
|
|
if(fileId || [LeaImageViewController isUrlSupported:[NSURL URLWithString:each]]) {
|
|
[realUrls addObject:each];
|
|
}
|
|
}
|
|
|
|
// 得到当前的url
|
|
NSUInteger count = [realUrls count];
|
|
if(count < 1) {
|
|
return;
|
|
}
|
|
int curIndex = 0;
|
|
NSString *curUrl = realUrls[0];
|
|
for(int i = 0; i < count; ++i) {
|
|
NSString *each = realUrls[i];
|
|
if([each isEqualToString:curUrlStr]) {
|
|
curUrl = each;
|
|
curIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
LeaImageSliderViewController *vc2 = [[LeaImageSliderViewController alloc] init];
|
|
vc2.curUrl = curUrl;
|
|
vc2.urlArr = realUrls;
|
|
vc2.curIndex = curIndex;
|
|
vc2.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
|
|
vc2.modalPresentationStyle = UIModalPresentationFullScreen;
|
|
[self presentViewController:vc2 animated:YES completion:nil];
|
|
|
|
return;
|
|
|
|
NSString *fileId = [Common getFileIdFromUrl:url];
|
|
if (!fileId) {
|
|
// return;
|
|
}
|
|
// self.selectedMediaID = fileId;
|
|
/*
|
|
// 表示已经有了
|
|
if(self.actionSheet) {
|
|
return;
|
|
}
|
|
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel", nil) destructiveButtonTitle:nil otherButtonTitles:NSLocalizedString(@"Save Image", nil), nil];
|
|
[actionSheet showInView:self.view];
|
|
actionSheet.tag = WPViewControllerActionSheetImageUploadRetry;
|
|
self.actionSheet = actionSheet;
|
|
*/
|
|
|
|
NSURL *urlU = [NSURL URLWithString:url];
|
|
UIViewController *controller = nil;
|
|
BOOL isSupportedNatively = [LeaImageViewController isUrlSupported:urlU];
|
|
|
|
UIImage *img;
|
|
if(fileId) {
|
|
NSString *absPath = [FileService getFileAbsPathByFileIdOrServerFileId:fileId];
|
|
img = [[UIImage alloc] initWithContentsOfFile:absPath];
|
|
}
|
|
if (isSupportedNatively) {
|
|
controller = [[LeaImageViewController alloc] initWithImage:img andURL:urlU];
|
|
}
|
|
/*
|
|
else if (imageControl.linkURL) {
|
|
LeaWebViewController *webViewController = [LeaWebViewController webViewControllerWithURL:imageControl.linkURL];
|
|
controller = [[UINavigationController alloc] initWithRootViewController:webViewController];
|
|
}*/
|
|
else {
|
|
controller = [[LeaImageViewController alloc] initWithImage:img];
|
|
}
|
|
|
|
if ([controller isKindOfClass:[LeaImageViewController class]]) {
|
|
controller.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
|
|
controller.modalPresentationStyle = UIModalPresentationFullScreen;
|
|
}
|
|
|
|
// LeaImagePagerViewController *vc = [[LeaImagePagerViewController alloc] init];
|
|
LeaImageSliderViewController *vc = [[LeaImageSliderViewController alloc] init];
|
|
[self presentViewController:vc animated:YES completion:nil];
|
|
}
|
|
|
|
- (void)showPromptForVideoWithID:(NSString *)videoId
|
|
{
|
|
if (videoId.length == 0){
|
|
return;
|
|
}
|
|
NSProgress *progress = self.mediaAdded[videoId];
|
|
if (!progress.cancelled){
|
|
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Stop Upload" otherButtonTitles:nil];
|
|
[actionSheet showInView:self.view];
|
|
actionSheet.tag = WPViewControllerActionSheetVideoUploadStop;
|
|
} else {
|
|
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Remove Video" otherButtonTitles:@"Retry Upload", nil];
|
|
[actionSheet showInView:self.view];
|
|
actionSheet.tag = WPViewControllerActionSheetVideoUploadRetry;
|
|
}
|
|
self.selectedMediaID = videoId;
|
|
}
|
|
|
|
// 选择图片
|
|
- (void)showPhotoPicker
|
|
{
|
|
[self.editorView saveSelection];
|
|
|
|
WPMediaPickerViewController * mediaPicker = [[WPMediaPickerViewController alloc] init];
|
|
mediaPicker.showMostRecentFirst = YES; // 防止拍照后崩溃
|
|
mediaPicker.delegate = self;
|
|
[self presentViewController:mediaPicker animated:YES completion:nil];
|
|
|
|
/*
|
|
|
|
CTAssetsPickerController *picker = [[CTAssetsPickerController alloc] init];
|
|
picker.delegate = self;
|
|
|
|
UIBarButtonItem *barButtonItem = [UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], [CTAssetsPickerController class], nil];
|
|
[barButtonItem setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateNormal];
|
|
[barButtonItem setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateDisabled];
|
|
|
|
// Only show photos for now (not videos)
|
|
picker.assetsFilter = [ALAssetsFilter allPhotos];
|
|
|
|
[self presentViewController:picker animated:YES completion:nil];
|
|
picker.childNavigationController.navigationBar.translucent = NO;
|
|
*/
|
|
|
|
/*
|
|
|
|
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
|
|
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
|
|
picker.delegate = self;
|
|
picker.allowsEditing = NO;
|
|
picker.navigationBar.translucent = NO;
|
|
picker.modalPresentationStyle = UIModalPresentationCurrentContext;
|
|
picker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:picker.sourceType];
|
|
[self.navigationController presentViewController:picker animated:YES completion:nil];
|
|
|
|
*/
|
|
}
|
|
|
|
#pragma mark - WPMediaPickerViewControllerDelegate
|
|
|
|
- (void)mediaPickerController:(WPMediaPickerViewController *)picker didFinishPickingAssets:(NSArray *)assets
|
|
{
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
// assets contains WPMediaAsset objects.
|
|
[self addMediaAssets:assets];
|
|
}
|
|
|
|
// 点击取消
|
|
- (void)mediaPickerControllerDidCancel:(id)picker
|
|
{
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
}
|
|
|
|
/*
|
|
#pragma mark - CTAssetsPickerControllerDelegate
|
|
|
|
- (void)assetsPickerController:(CTAssetsPickerController *)picker didFinishPickingAssets:(NSArray *)assets
|
|
{
|
|
[self dismissViewControllerAnimated:YES completion:^{
|
|
[self addMediaAssets:assets];
|
|
}];
|
|
}
|
|
|
|
- (BOOL)assetsPickerController:(CTAssetsPickerController *)picker shouldSelectAsset:(ALAsset *)asset
|
|
{
|
|
if ([asset valueForProperty:ALAssetPropertyType] == ALAssetTypePhoto) {
|
|
// If the image is from a shared photo stream it may not be available locally to be used
|
|
if (!asset.defaultRepresentation) {
|
|
[LeaAlert showAlertWithTitle:NSLocalizedString(@"Image unavailable", @"The title for an alert that says the image the user selected isn't available.")
|
|
message:NSLocalizedString(@"This Photo Stream image cannot be added to note. Try saving it to your Camera Roll before.", @"User information explaining that the image is not available locally. This is normally related to share photo stream images.") withSupportButton:NO];
|
|
return NO;
|
|
}
|
|
if (picker.selectedAssets.count >= MaximumNumberOfPictures) {
|
|
[LeaAlert showAlertWithTitle:nil
|
|
message:[NSString stringWithFormat:NSLocalizedString(@"You can only add %i photos at a time.", @"User information explaining that you can only select an x number of images."), MaximumNumberOfPictures] withSupportButton:NO];
|
|
return NO;
|
|
}
|
|
return YES;
|
|
} else {
|
|
return NO;
|
|
}
|
|
}
|
|
*/
|
|
|
|
- (NSString *) getImageUrl:(NSString *) fileId
|
|
{
|
|
return [NSString stringWithFormat:@"leanote://getImage?fileId=%@", fileId];
|
|
}
|
|
- (void)addMediaAssets:(NSArray *)assets
|
|
{
|
|
NSString *urls = @"[";
|
|
for (ALAsset *asset in assets) {
|
|
NSString *fileId = [self addImageAssetToContent:asset];
|
|
urls = [NSString stringWithFormat:@"%@'%@',", urls, [self getImageUrl:fileId]];
|
|
}
|
|
urls = [NSString stringWithFormat:@"%@]", urls];
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[self.editorView insertImage:urls alt:@""];
|
|
});
|
|
}
|
|
|
|
// 添加图片到内容中
|
|
- (NSString *)addImageAssetToContent:(ALAsset *)asset
|
|
{
|
|
UIImage *image = [UIImage imageWithCGImage:asset.defaultRepresentation.fullScreenImage];
|
|
NSData *data = UIImageJPEGRepresentation(image, 0.7);
|
|
NSString *imageID = [Common newObjectId];
|
|
|
|
NSString *relativePath = [NSString stringWithFormat:@"%@/%@.jpg", @"images", imageID];
|
|
|
|
// 图片写到doc/images目录下
|
|
NSString *path = [NSString stringWithFormat:@"%@/%@", [Common getDocPath], relativePath];
|
|
[data writeToFile:path atomically:YES];
|
|
|
|
// 一条本地记录
|
|
File *file = [FileService addLocalFile:relativePath];
|
|
|
|
return file.fileId;
|
|
}
|
|
|
|
// 视频, 不允许!!
|
|
/*
|
|
- (void)addVideoAssetToContent:(ALAsset *)originalAsset
|
|
{
|
|
UIImage *image = [UIImage imageWithCGImage:originalAsset.defaultRepresentation.fullScreenImage];
|
|
NSData *data = UIImageJPEGRepresentation(image, 0.7);
|
|
NSString *posterImagePath = [NSString stringWithFormat:@"%@/%@.jpg", NSTemporaryDirectory(), [[NSUUID UUID] UUIDString]];
|
|
[data writeToFile:posterImagePath atomically:YES];
|
|
NSString *videoID = [[NSUUID UUID] UUIDString];
|
|
[self.editorView insertInProgressVideoWithID:videoID
|
|
usingPosterImage:[[NSURL fileURLWithPath:posterImagePath] absoluteString]];
|
|
ALAssetRepresentation *representation = originalAsset.defaultRepresentation;
|
|
AVAsset *asset = [AVURLAsset URLAssetWithURL:representation.url options:nil];
|
|
NSString *videoPath = [NSString stringWithFormat:@"%@%@.mov", NSTemporaryDirectory(), videoID];
|
|
NSString *presetName = AVAssetExportPresetPassthrough;
|
|
AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:asset presetName:presetName];
|
|
session.outputFileType = representation.UTI;
|
|
session.shouldOptimizeForNetworkUse = YES;
|
|
session.outputURL = [NSURL fileURLWithPath:videoPath];
|
|
[session exportAsynchronouslyWithCompletionHandler:^{
|
|
if (session.status != AVAssetExportSessionStatusCompleted) {
|
|
return;
|
|
}
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
NSProgress *progress = [[NSProgress alloc] initWithParent:nil
|
|
userInfo:@{@"videoID": videoID, @"url": videoPath, @"poster": posterImagePath }];
|
|
progress.cancellable = YES;
|
|
progress.totalUnitCount = 100;
|
|
[NSTimer scheduledTimerWithTimeInterval:0.1
|
|
target:self
|
|
selector:@selector(timerFireMethod:)
|
|
userInfo:progress
|
|
repeats:YES];
|
|
self.mediaAdded[videoID] = progress;
|
|
});
|
|
}];
|
|
}
|
|
*/
|
|
|
|
// 添加图片到笔记中
|
|
- (void)addAssetToContent:(NSURL *)assetURL
|
|
{
|
|
ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
|
|
[assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {
|
|
|
|
if ([asset valueForProperty:ALAssetPropertyType] == ALAssetTypeVideo) {
|
|
NSLog(@"视频不允许添加");
|
|
// [self addVideoAssetToContent:asset];
|
|
} if ([asset valueForProperty:ALAssetPropertyType] == ALAssetTypePhoto) {
|
|
NSLog(@"图片插入成功!");
|
|
[self addImageAssetToContent:asset];
|
|
}
|
|
} failureBlock:^(NSError *error) {
|
|
NSLog(@"图片插入失败!");
|
|
DDLogInfo(@"Failed to insert media: %@", [error localizedDescription]);
|
|
}];
|
|
}
|
|
|
|
- (void)timerFireMethod:(NSTimer *)timer
|
|
{
|
|
NSProgress *progress = (NSProgress *)timer.userInfo;
|
|
progress.completedUnitCount++;
|
|
NSString *imageID = progress.userInfo[@"imageID"];
|
|
if (imageID) {
|
|
[self.editorView setProgress:progress.fractionCompleted onImage:imageID];
|
|
// Uncomment this code if you need to test a failed image upload
|
|
// if (progress.fractionCompleted >= 0.15){
|
|
// [progress cancel];
|
|
// [self.editorView markImage:imageID failedUploadWithMessage:@"Failed"];
|
|
// [timer invalidate];
|
|
// }
|
|
if (progress.fractionCompleted >= 1) {
|
|
[self.editorView replaceLocalImageWithRemoteImage:[[NSURL fileURLWithPath:progress.userInfo[@"url"]] absoluteString] uniqueId:imageID];
|
|
[timer invalidate];
|
|
}
|
|
return;
|
|
}
|
|
|
|
return;
|
|
// 以下是视频
|
|
|
|
NSString *videoID = progress.userInfo[@"videoID"];
|
|
if (videoID) {
|
|
[self.editorView setProgress:progress.fractionCompleted onVideo:videoID];
|
|
// Uncomment this code if you need to test a failed video upload
|
|
// if (progress.fractionCompleted >= 0.15) {
|
|
// [progress cancel];
|
|
// [self.editorView markVideo:videoID failedUploadWithMessage:@"Failed"];
|
|
// [timer invalidate];
|
|
// }
|
|
if (progress.fractionCompleted >= 1) {
|
|
NSString * videoURL = [[NSURL fileURLWithPath:progress.userInfo[@"url"]] absoluteString];
|
|
NSString * posterURL = [[NSURL fileURLWithPath:progress.userInfo[@"poster"]] absoluteString];
|
|
[self.editorView replaceLocalVideoWithID:videoID
|
|
forRemoteVideo:videoURL
|
|
remotePoster:posterURL
|
|
videoPress:videoID];
|
|
[self.videoPressCache setObject:@ {@"source":videoURL, @"poster":posterURL} forKey:videoID];
|
|
[timer invalidate];
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 选择图片代理
|
|
#pragma mark - UIImagePickerControllerDelegate methods
|
|
|
|
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
|
|
{
|
|
[self.navigationController dismissViewControllerAnimated:YES completion:^{
|
|
NSURL *assetURL = info[UIImagePickerControllerReferenceURL];
|
|
[self addAssetToContent:assetURL];
|
|
}];
|
|
}
|
|
|
|
// 点击工具栏
|
|
|
|
#pragma mark - UIActionSheetDelegate
|
|
|
|
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
|
|
{
|
|
self.actionSheet = nil;
|
|
|
|
if (actionSheet.tag == WPViewControllerActionSheetImageUploadStop){
|
|
if (buttonIndex == actionSheet.destructiveButtonIndex) {
|
|
[self.editorView removeImage:self.selectedMediaID];
|
|
}
|
|
|
|
// 下载图片
|
|
} else if (actionSheet.tag == WPViewControllerActionSheetImageUploadRetry){
|
|
if (buttonIndex == actionSheet.destructiveButtonIndex) {
|
|
// [self.editorView removeImage:self.selectedMediaID];
|
|
}
|
|
else if (buttonIndex == actionSheet.firstOtherButtonIndex) {
|
|
NSString *absPath = [FileService getFileAbsPathByFileIdOrServerFileId:self.selectedMediaID];
|
|
if(!absPath) {
|
|
[self showErrorMsg:NSLocalizedString(@"Save image failed", nil) ret:nil];
|
|
return;
|
|
}
|
|
UIImage *image = [UIImage imageWithContentsOfFile:absPath];
|
|
|
|
UIImageWriteToSavedPhotosAlbum(image, nil, nil,nil);
|
|
|
|
[self showSuccessMsg:NSLocalizedString(@"Save image successful", nil)];
|
|
}
|
|
|
|
} else if (actionSheet.tag == WPViewControllerActionSheetVideoUploadStop){
|
|
if (buttonIndex == actionSheet.destructiveButtonIndex) {
|
|
[self.editorView removeVideo:self.selectedMediaID];
|
|
}
|
|
} else if (actionSheet.tag == WPViewControllerActionSheetVideoUploadRetry){
|
|
if (buttonIndex == actionSheet.destructiveButtonIndex) {
|
|
[self.editorView removeVideo:self.selectedMediaID];
|
|
} else if (buttonIndex == actionSheet.firstOtherButtonIndex) {
|
|
NSProgress * progress = [[NSProgress alloc] initWithParent:nil userInfo:@{@"videoID":self.selectedMediaID}];
|
|
progress.totalUnitCount = 100;
|
|
[NSTimer scheduledTimerWithTimeInterval:0.1
|
|
target:self
|
|
selector:@selector(timerFireMethod:)
|
|
userInfo:progress
|
|
repeats:YES];
|
|
self.mediaAdded[self.selectedMediaID] = progress;
|
|
[self.editorView unmarkVideoFailedUpload:self.selectedMediaID];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@end
|