diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml deleted file mode 100644 index e3bb963fff..0000000000 --- a/.buildkite/pipeline.yml +++ /dev/null @@ -1,16 +0,0 @@ -steps: - - block: ":rocket: Release!" - prompt: "Fill out the details for release" - if: 'build.message =~ /^release\$/i' - fields: - - text: "VERSION" - key: "version" - - - label: ":hammer_and_pick: Build" - command: - - "nvm install" - - "npm install" - - "npm run test" - - "npm run build" - - "[[ $BUILDKITE_PULL_REQUEST == 'false' ]] && npm run release && npm run demo || true" - timeout_in_minutes: 15 diff --git a/.github/workflows/label-waiting-for-response.yml b/.github/workflows/label-waiting-for-response.yml new file mode 100644 index 0000000000..825bfec6f8 --- /dev/null +++ b/.github/workflows/label-waiting-for-response.yml @@ -0,0 +1,138 @@ +name: Auto Label Issues + +on: + issue_comment: + types: [created] + workflow_dispatch: + inputs: + label-all-issues: + description: 'Add label to all open issues' + type: boolean + default: false + required: false + +jobs: + add-label-single: + runs-on: ubuntu-latest + if: | + github.event_name == 'issue_comment' && + github.event.issue.user.login != github.event.comment.user.login + + steps: + - name: Check if commenter is maintainer + id: check-maintainer + uses: actions/github-script@v7 + with: + script: | + const response = await github.rest.repos.getCollaboratorPermissionLevel({ + owner: context.repo.owner, + repo: context.repo.repo, + username: context.payload.comment.user.login + }); + + const isMaintianer = ['admin', 'write'].includes(response.data.permission); + return isMaintianer; + + - name: Add waiting-for-response label + if: steps.check-maintainer.outputs.result == 'true' + uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: ['waiting-for-response'] + }); + + add-label-all: + runs-on: ubuntu-latest + if: | + github.event_name == 'workflow_dispatch' && + github.event.inputs.label-all-issues == 'true' + + steps: + - name: Process all open issues + uses: actions/github-script@v7 + with: + script: | + async function isMaintianer(username) { + try { + const response = await github.rest.repos.getCollaboratorPermissionLevel({ + owner: context.repo.owner, + repo: context.repo.repo, + username: username + }); + return ['admin', 'write'].includes(response.data.permission); + } catch (error) { + console.error(`Error checking permissions for ${username}:`, error); + return false; + } + } + + async function getLastComment(issueNumber) { + try { + const comments = await github.paginate(github.rest.issues.listComments, { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + per_page: 100 + }); + + // Return the most recent comment, or null if no comments + return comments.length > 0 ? comments[comments.length - 1] : null; + } catch (error) { + console.error(`Error fetching comments for issue #${issueNumber}:`, error); + return null; + } + } + + // Get all open issues + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100 + }); + + for (const issue of issues) { + try { + console.log(`Processing issue #${issue.number}...`); + + // Get the last comment + const lastComment = await getLastComment(issue.number); + + // Skip if no comments + if (!lastComment) { + console.log(`No comments found on issue #${issue.number}, skipping`); + continue; + } + + // Check if last commenter is a maintainer + const lastCommenterIsMaintainer = await isMaintianer(lastComment.user.login); + + // Skip if last commenter is not a maintainer + if (!lastCommenterIsMaintainer) { + console.log(`Last comment on issue #${issue.number} is not from a maintainer, skipping`); + continue; + } + + // Skip if last commenter is the issue author + if (lastComment.user.login === issue.user.login) { + console.log(`Last comment on issue #${issue.number} is from the issue author, skipping`); + continue; + } + + // Add the label + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: ['waiting-for-response'] + }); + + console.log(`Added label to issue #${issue.number}`); + } catch (error) { + console.error(`Error processing issue #${issue.number}:`, error); + } + } \ No newline at end of file diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 178a5650a5..0000000000 --- a/.npmignore +++ /dev/null @@ -1,256 +0,0 @@ -example/ -docs/ -docuilib/ -eslint-rules/ -extensions/ -node_modules/ -.npmignore -.watchmanconfig -src/**/__tests__/*.* - -################# -# from .gitignore: -################ - - -############ -# Node -############ -# Logs -logs -*.log -npm-debug.log* - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules -jspm_packages - -# Optional npm cache directory -.npm - -# Optional REPL history -.node_repl_history - -################ -# JetBrains -################ -.idea - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -/out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - - -############ -# iOS -############ -# Xcode -# -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## Build generated -ios/build/ -ios/DerivedData/ - -## Various settings -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -ios/xcuserdata/ - -## Other -*.moved-aside -*.xcuserstate - -## Obj-C/Swift specific -*.hmap -*.ipa -*.dSYM.zip -*.dSYM - -# CocoaPods -# -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control -# -ios/Pods/ - -# Carthage -# -# Add this line if you want to avoid checking in source code from Carthage dependencies. -# Carthage/Checkouts - -Carthage/Build - -# fastlane -# -# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the -# screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md - -fastlane/report.xml -fastlane/screenshots - - -############ -# Android -############ -# Built application files -*.apk -*.ap_ - -# Files for the Dalvik VM -*.dex - -# Java class files -*.class - -# Generated files -android/bin/ -android/gen/ -android/out/ - -# Gradle files -android/.gradle/ -android/build/ -android/*/build/ - -# Local configuration file (sdk path, etc) -local.properties - -# Proguard folder generated by Eclipse -android/proguard/ - -# Log Files -*.log - -# Android Studio Navigation editor temp files -android/.navigation/ - -# Android Studio captures folder -android/captures/ - -# Intellij -*.iml - -# Keystore files -*.jks - -################## -# React-Native -################## -# OSX -# -.DS_Store - -# Xcode -# -build/ -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata -*.xccheckout -*.moved-aside -DerivedData -*.hmap -*.ipa -*.xcuserstate -project.xcworkspace - -# Android/IJ -# -.idea -android/.idea -android/.gradle -android/local.properties - -# node.js -# -node_modules/ -npm-debug.log - -# BUCK -buck-out/ -\.buckd/ -android/app/libs -android/keystores/debug.keystore - -# OURS -# -test/ -ios/ -android/ -demo/ -expoDemo/ -webDemo/ -uilib-docs/ -markdowns/ -.babelrc -# typings/ -# eslint-rules/ -scripts/* -!scripts/prReleaseNotesCommon.js -demo-app.component.js -index.android.js -index.ios.js - -# Typescript -# ignore the .ts files -*.ts -*.tsx -# include the .d.ts files -!*.d.ts - -!testkit/*.ts diff --git a/README.md b/README.md index 5829ebe3e3..bf4713aa92 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ --- -[![Build Status](https://travis-ci.org/wix/react-native-ui-lib.svg?branch=master)](https://travis-ci.org/wix/react-native-ui-lib) +[![Build Status](https://github.com/wix/react-native-ui-lib/blob/master/ios/rnuilib/Images.xcassets/AppIcon.appiconset/20.png?raw=true)](https://buildkite.com/wix-mobile-oss/react-native-ui-lib) [![npm](https://img.shields.io/npm/v/react-native-ui-lib.svg)](https://www.npmjs.com/package/react-native-ui-lib) [![NPM Downloads](https://img.shields.io/npm/dm/react-native-ui-lib.svg?style=flat)](https://www.npmjs.com/package/react-native-ui-lib) Follow on Twitter diff --git a/demo/package.json b/demo/package.json index 9d67ce93a9..080c1a8f63 100644 --- a/demo/package.json +++ b/demo/package.json @@ -12,8 +12,7 @@ "url": "git+https://github.com/wix/react-native-ui-lib.git" }, "scripts": { - "release": "node ./scripts/release.js", - "demoRelease": "node ./scripts/demoRelease.js" + "releaseDemo": "node ./scripts/releaseDemo.js" }, "dependencies": { "light-date": "^1.2.0" diff --git a/demo/scripts/release.js b/demo/scripts/release.js deleted file mode 100644 index b951f6e505..0000000000 --- a/demo/scripts/release.js +++ /dev/null @@ -1,67 +0,0 @@ -const cp = require('child_process'); -const p = require('path'); -const semver = require('semver'); - -function execSync(cmd) { - cp.execSync(cmd, { stdio: ['inherit', 'inherit', 'inherit'] }); -} - -function execSyncRead(cmd) { - return String(cp.execSync(cmd, { stdio: ['inherit', 'pipe', 'inherit'] })).trim(); -} - -function execSyncSilently(cmd) { - cp.execSync(cmd, { stdio: ['ignore', 'ignore', 'ignore'] }); -} - -function validateEnv() { - if (!process.env.CI || !process.env.TRAVIS) { - throw new Error('releasing is only available from Travis CI'); - } - - if (process.env.TRAVIS_BRANCH !== 'master') { - console.error(`not publishing on branch ${process.env.TRAVIS_BRANCH}`); - return false; - } - - if (process.env.TRAVIS_PULL_REQUEST !== 'false') { - console.error(`not publishing as triggered by pull request ${process.env.TRAVIS_PULL_REQUEST}`); - return false; - } - - return true; -} - -function calcNewVersion() { - const latestVersion = execSyncRead(`npm view ${process.env.npm_package_name}@latest version`); - console.log(`latest version is: ${latestVersion}`); - console.log(`package version is: ${process.env.npm_package_version}`); - if (semver.gt(process.env.npm_package_version, latestVersion)) { - return semver.inc(process.env.npm_package_version, 'patch'); - } else { - return semver.inc(latestVersion, 'patch'); - } -} - -function copyNpmRc() { - execSync('rm -f package-lock.json'); - const npmrcPath = p.resolve(`${__dirname}/.npmrc`); - execSync(`cp -rf ${npmrcPath} .`); -} - -function tagAndPublish(newVersion) { - console.log(`new version is: ${newVersion}`); - execSync(`npm version ${newVersion} -m "v${newVersion} [ci skip]"`); - execSync('npm publish --tag latest'); - execSyncSilently('git push deploy --tags'); -} - -function run() { - if (!validateEnv()) { - return; - } - copyNpmRc(); - tagAndPublish(calcNewVersion()); -} - -run(); diff --git a/demo/scripts/demoRelease.js b/demo/scripts/releaseDemo.js similarity index 100% rename from demo/scripts/demoRelease.js rename to demo/scripts/releaseDemo.js diff --git a/demo/showcase/Docs/thumbnail-horizontal.png b/demo/showcase/Docs/thumbnail-horizontal.png new file mode 100644 index 0000000000..d6850ec66a Binary files /dev/null and b/demo/showcase/Docs/thumbnail-horizontal.png differ diff --git a/demo/showcase/Docs/thumbnail-phoneSize.png b/demo/showcase/Docs/thumbnail-phoneSize.png new file mode 100644 index 0000000000..c2202c57c7 Binary files /dev/null and b/demo/showcase/Docs/thumbnail-phoneSize.png differ diff --git a/demo/showcase/Docs/thumbnail-veryWide.png b/demo/showcase/Docs/thumbnail-veryWide.png new file mode 100644 index 0000000000..b880559cee Binary files /dev/null and b/demo/showcase/Docs/thumbnail-veryWide.png differ diff --git a/demo/src/screens/__tests__/__snapshots__/AvatarScreen.spec.js.snap b/demo/src/screens/__tests__/__snapshots__/AvatarScreen.spec.js.snap index 42c2931ed1..c38872384f 100644 --- a/demo/src/screens/__tests__/__snapshots__/AvatarScreen.spec.js.snap +++ b/demo/src/screens/__tests__/__snapshots__/AvatarScreen.spec.js.snap @@ -1450,6 +1450,7 @@ exports[`AvatarScreen renders screen 1`] = ` assetGroup="icons" onError={[Function]} onLoad={[Function]} + onLoadStart={[Function]} source={ { "uri": "https://static.pexels.com/photos/60628/flower-garden-blue-sky-hokkaido-japan-60628.jpeg", diff --git a/demo/src/screens/componentScreens/PickerScreen.tsx b/demo/src/screens/componentScreens/PickerScreen.tsx index 725765f19c..4a2c20fa0d 100644 --- a/demo/src/screens/componentScreens/PickerScreen.tsx +++ b/demo/src/screens/componentScreens/PickerScreen.tsx @@ -191,7 +191,6 @@ export default class PickerScreen extends Component {