Merge pull request #1893 from mattermost/release-1.10

Merge Release 1.10 into master
This commit is contained in:
Elias Nahum 2018-07-05 19:27:01 -04:00 committed by GitHub
commit ec3cd8d878
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 102 additions and 86 deletions

View file

@ -1428,40 +1428,6 @@ SOFTWARE.
---
## youtube-video-id
This product contains 'youtube-video-id', Extracts the YouTube video ID from a url or string.
* HOMEPAGE:
* https://github.com/remarkablemark/youtube-video-id
* LICENSE:
MIT License
Copyright (c) 2016 Menglin "Mark" Xu <mark@remarkablemark.org>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
## react-native-video
This product contains 'react-native-video', A <Video> component for react-native.

View file

@ -113,7 +113,7 @@ android {
applicationId "com.mattermost.rnbeta"
minSdkVersion 21
targetSdkVersion 23
versionCode 123
versionCode 124
versionName "1.10.0"
ndk {
abiFilters "armeabi-v7a", "x86"

View file

@ -13,14 +13,13 @@ import {
View,
} from 'react-native';
import {YouTubeStandaloneAndroid, YouTubeStandaloneIOS} from 'react-native-youtube';
import youTubeVideoId from 'youtube-video-id';
import ProgressiveImage from 'app/components/progressive_image';
import CustomPropTypes from 'app/constants/custom_prop_types';
import {emptyFunction} from 'app/utils/general';
import ImageCacheManager from 'app/utils/image_cache_manager';
import {isImageLink, isYoutubeLink} from 'app/utils/url';
import {getYouTubeVideoId, isImageLink, isYoutubeLink} from 'app/utils/url';
const MAX_IMAGE_HEIGHT = 150;
@ -87,7 +86,7 @@ export default class PostBodyAdditionalContent extends PureComponent {
if (isImageLink(link)) {
imageUrl = link;
} else if (isYoutubeLink(link)) {
const videoId = youTubeVideoId(link);
const videoId = getYouTubeVideoId(link);
imageUrl = `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`;
ImageCacheManager.cache(null, `https://i.ytimg.com/vi/${videoId}/default.jpg`, () => true);
}
@ -156,7 +155,7 @@ export default class PostBodyAdditionalContent extends PureComponent {
if (link) {
if (isYouTube) {
const videoId = youTubeVideoId(link);
const videoId = getYouTubeVideoId(link);
const imgUrl = `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`;
const thumbUrl = `https://i.ytimg.com/vi/${videoId}/default.jpg`;
@ -291,6 +290,35 @@ export default class PostBodyAdditionalContent extends PureComponent {
return previewComponent ? {...previewComponent.props} : {};
};
getYouTubeTime = (link) => {
const timeRegex = /[\\?&](t|start|time_continue)=([0-9]+h)?([0-9]+m)?([0-9]+s?)/;
const time = link.match(timeRegex);
if (!time || !time[0]) {
return 0;
}
const hours = time[2] ? time[2].match(/([0-9]+)h/) : null;
const minutes = time[3] ? time[3].match(/([0-9]+)m/) : null;
const seconds = time[4] ? time[4].match(/([0-9]+)s?/) : null;
let ticks = 0;
if (hours && hours[1]) {
ticks += parseInt(hours[1], 10) * 3600;
}
if (minutes && minutes[1]) {
ticks += parseInt(minutes[1], 10) * 60;
}
if (seconds && seconds[1]) {
ticks += parseInt(seconds[1], 10);
}
return ticks;
};
goToImagePreview = (passProps) => {
this.props.navigator.showModal({
screen: 'ImagePreview',
@ -343,7 +371,7 @@ export default class PostBodyAdditionalContent extends PureComponent {
playYouTubeVideo = () => {
const {link} = this.props;
const videoId = youTubeVideoId(link);
const videoId = getYouTubeVideoId(link);
const startTime = this.getYouTubeTime(link);
if (Platform.OS === 'ios') {
@ -364,35 +392,6 @@ export default class PostBodyAdditionalContent extends PureComponent {
}
};
getYouTubeTime = (link) => {
const timeRegex = /[\\?&](t|start|time_continue)=([0-9]+h)?([0-9]+m)?([0-9]+s?)/;
const time = link.match(timeRegex);
if (!time || !time[0]) {
return 0;
}
const hours = time[2] ? time[2].match(/([0-9]+)h/) : null;
const minutes = time[3] ? time[3].match(/([0-9]+)m/) : null;
const seconds = time[4] ? time[4].match(/([0-9]+)s?/) : null;
let ticks = 0;
if (hours && hours[1]) {
ticks += parseInt(hours[1], 10) * 3600;
}
if (minutes && minutes[1]) {
ticks += parseInt(minutes[1], 10) * 60;
}
if (seconds && seconds[1]) {
ticks += parseInt(seconds[1], 10);
}
return ticks;
};
render() {
const {link, openGraphData, postProps} = this.props;
const {linkLoadError} = this.state;

View file

@ -94,3 +94,25 @@ export function getScheme(url) {
return match && match[1];
}
export function getYouTubeVideoId(link) {
// https://youtube.com/watch?v=<id>
let match = (/youtube\.com\/watch\?\S*\bv=([a-zA-Z0-9_-]{6,11})/g).exec(link);
if (match) {
return match[1];
}
// https://youtube.com/embed/<id>
match = (/youtube\.com\/embed\/([a-zA-Z0-9_-]{6,11})/g).exec(link);
if (match) {
return match[1];
}
// https://youtu.be/<id>
match = (/youtu.be\/([a-zA-Z0-9_-]{6,11})/g).exec(link);
if (match) {
return match[1];
}
return '';
}

View file

@ -42,4 +42,23 @@ describe('UrlUtils', () => {
expect(UrlUtils.isImageLink(link)).toEqual(true);
});
});
describe('getYouTubeVideoId', () => {
const tests = [
['https://youtu.be/zrFWrmPgfzc', 'zrFWrmPgfzc'],
['https://youtu.be/zrFWrmPgfzc?t=10s', 'zrFWrmPgfzc'],
['https://www.youtube.com/watch?v=zrFWrmPgfzc&feature=youtu.be', 'zrFWrmPgfzc'],
['https://www.youtube.com/watch?v=zrFWrmPgfzc&t=10s', 'zrFWrmPgfzc'],
['https://www.youtube.com/watch?t=10s&v=zrFWrmPgfzc', 'zrFWrmPgfzc'],
];
for (const test of tests) {
const input = test[0];
const expected = test[1];
it(input, () => {
expect(UrlUtils.getYouTubeVideoId(input)).toEqual(expected);
});
}
});
});

View file

@ -42,10 +42,10 @@ platform :ios do
git_actions()
if ENV['MATTERMOST_WEBHOOK_URL']
pretext = '#### New iOS beta published to TestFlight'
pretext = '#### New iOS beta published to TestFlight -> @qateam'
msg = '#ios-beta should be available in TestFlight soon, you can sign up as a beta tester [here](https://mattermost-fastlane.herokuapp.com/)'
if !ENV['BETA_BUILD'].nil? && !ENV['BETA_BUILD'].empty? && ENV['BETA_BUILD'] != 'true'
pretext = '#### New iOS released ready to be published'
pretext = '#### New iOS released ready to be published -> @qateam'
msg = '#ios-release has been cut and should be available for [download](https://itunes.apple.com/us/app/mattermost/id1257222717?mt=8) soon.'
end
send_message_for_ios(
@ -307,10 +307,10 @@ platform :android do
git_actions()
if ENV['MATTERMOST_WEBHOOK_URL'] && !ENV['MATTERMOST_WEBHOOK_URL'].nil? && !ENV['MATTERMOST_WEBHOOK_URL'].empty?
pretext = '#### New Android beta published to Google Play'
pretext = '#### New Android beta published to Google Play -> @qateam'
msg = '#android-beta available for testing, you can sign up as a beta tester [here](https://play.google.com/apps/testing/com.mattermost.rnbeta)'
if !ENV['BETA_BUILD'].nil? && !ENV['BETA_BUILD'].empty? && ENV['BETA_BUILD'] != 'true'
pretext = '#### New Android released ready to be published'
pretext = '#### New Android released ready to be published -> @qateam'
msg = '#android-release has been cut and should be available for [download](https://play.google.com/store/apps/details?id=com.mattermost.rn&hl=en) soon.'
end
send_message_for_android(

View file

@ -85,7 +85,6 @@
7FF7BE6E1FDEE5E8005E55FE /* MattermostBucket.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FF7BE6C1FDEE5E8005E55FE /* MattermostBucket.m */; };
7FF7BE6F1FDF3CE4005E55FE /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FDF290C1E1F4B4E00DBBE56 /* libRNVectorIcons.a */; };
7FF7BE701FDF3EE7005E55FE /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2DCFD31D3F4A4154822AB532 /* Ionicons.ttf */; };
7FF7BE711FE004A3005E55FE /* libRNDeviceInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 37DD11281E79EBE1004111BA /* libRNDeviceInfo.a */; };
7FFDB3191FE3566C009E3BCF /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 005346E5C0E542BFABAE1411 /* FontAwesome.ttf */; };
7FFE329E1FD9CB650038C7A0 /* ShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FFE329D1FD9CB650038C7A0 /* ShareViewController.m */; };
7FFE32A11FD9CB650038C7A0 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7FFE329F1FD9CB650038C7A0 /* MainInterface.storyboard */; };
@ -2532,7 +2531,7 @@
CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 123;
CURRENT_PROJECT_VERSION = 124;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
ENABLE_BITCODE = NO;
@ -2582,7 +2581,7 @@
CODE_SIGN_ENTITLEMENTS = Mattermost/Mattermost.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 123;
CURRENT_PROJECT_VERSION = 124;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = UQ8HT4Q2XM;
ENABLE_BITCODE = NO;

View file

@ -24,6 +24,23 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Clear keychain on first run in case of reinstallation
if (![[NSUserDefaults standardUserDefaults] objectForKey:@"FirstRun"]) {
NSString *service = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *query = @{
(__bridge NSString *)kSecClass: (__bridge id)(kSecClassGenericPassword),
(__bridge NSString *)kSecAttrService: service,
(__bridge NSString *)kSecReturnAttributes: (__bridge id)kCFBooleanTrue,
(__bridge NSString *)kSecReturnData: (__bridge id)kCFBooleanFalse
};
SecItemDelete((__bridge CFDictionaryRef) query);
[[NSUserDefaults standardUserDefaults] setValue:@YES forKey:@"FirstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

View file

@ -34,7 +34,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>123</string>
<string>124</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>

View file

@ -23,7 +23,7 @@
<key>CFBundleShortVersionString</key>
<string>1.10.0</string>
<key>CFBundleVersion</key>
<string>123</string>
<string>124</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>

View file

@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>123</string>
<string>124</string>
</dict>
</plist>

5
package-lock.json generated
View file

@ -18344,11 +18344,6 @@
"requires": {
"camelcase": "^4.1.0"
}
},
"youtube-video-id": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/youtube-video-id/-/youtube-video-id-0.0.2.tgz",
"integrity": "sha512-aipX3kMN/JBxa1oj6ip9GOBHxSjyAogmchbwDMyxo9JEN5tQWxvP6OBuoB1iYo9RD50uXZbcpRqaj2028/qFcQ=="
}
}
}

View file

@ -66,8 +66,7 @@
"semver": "5.5.0",
"shallow-equals": "1.0.0",
"tinycolor2": "1.4.1",
"url-parse": "1.4.0",
"youtube-video-id": "0.0.2"
"url-parse": "1.4.0"
},
"devDependencies": {
"babel-cli": "6.26.0",